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 1487ac3d00SMimi Zohar #define pr_fmt(fmt) "EVM: "fmt 1587ac3d00SMimi Zohar 163aafb1fbSPaul Gortmaker #include <linux/init.h> 1766dbc325SMimi Zohar #include <linux/crypto.h> 189b97b6cdSMimi Zohar #include <linux/audit.h> 1966dbc325SMimi Zohar #include <linux/xattr.h> 2066dbc325SMimi Zohar #include <linux/integrity.h> 213e1be52dSMimi Zohar #include <linux/evm.h> 2250d34394SIngo Molnar #include <linux/magic.h> 231886ab01SRoberto Sassu #include <linux/posix_acl_xattr.h> 2450d34394SIngo Molnar 25d46eb369SDmitry Kasatkin #include <crypto/hash.h> 265feeb611SMatthew Garrett #include <crypto/hash_info.h> 27613317bdSRyan Ware #include <crypto/algapi.h> 2866dbc325SMimi Zohar #include "evm.h" 2966dbc325SMimi Zohar 3066dbc325SMimi Zohar int evm_initialized; 3166dbc325SMimi Zohar 3217d7b0afSHernán Gonzalez static const char * const integrity_status_msg[] = { 33cdef685bSRoberto Sassu "pass", "pass_immutable", "fail", "fail_immutable", "no_label", 34cdef685bSRoberto Sassu "no_xattrs", "unknown" 359b97b6cdSMimi Zohar }; 36d3b33679SDmitry Kasatkin int evm_hmac_attrs; 3766dbc325SMimi Zohar 38fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = { 398c7a703eSRoberto Sassu {.name = XATTR_NAME_SELINUX, 4066dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX 418c7a703eSRoberto Sassu .enabled = true 4266dbc325SMimi Zohar #endif 438c7a703eSRoberto Sassu }, 448c7a703eSRoberto Sassu {.name = XATTR_NAME_SMACK, 4566dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK 468c7a703eSRoberto Sassu .enabled = true 478c7a703eSRoberto Sassu #endif 488c7a703eSRoberto Sassu }, 498c7a703eSRoberto Sassu {.name = XATTR_NAME_SMACKEXEC, 503e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 518c7a703eSRoberto Sassu .enabled = true 523e38df56SDmitry Kasatkin #endif 538c7a703eSRoberto Sassu }, 548c7a703eSRoberto Sassu {.name = XATTR_NAME_SMACKTRANSMUTE, 558c7a703eSRoberto Sassu #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 568c7a703eSRoberto Sassu .enabled = true 5766dbc325SMimi Zohar #endif 588c7a703eSRoberto Sassu }, 598c7a703eSRoberto Sassu {.name = XATTR_NAME_SMACKMMAP, 608c7a703eSRoberto Sassu #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 618c7a703eSRoberto Sassu .enabled = true 628c7a703eSRoberto Sassu #endif 638c7a703eSRoberto Sassu }, 648c7a703eSRoberto Sassu {.name = XATTR_NAME_APPARMOR, 65096b8546SMatthew Garrett #ifdef CONFIG_SECURITY_APPARMOR 668c7a703eSRoberto Sassu .enabled = true 67096b8546SMatthew Garrett #endif 688c7a703eSRoberto Sassu }, 698c7a703eSRoberto Sassu {.name = XATTR_NAME_IMA, 702fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE 718c7a703eSRoberto Sassu .enabled = true 722fe5d6deSMimi Zohar #endif 738c7a703eSRoberto Sassu }, 748c7a703eSRoberto Sassu {.name = XATTR_NAME_CAPS, 758c7a703eSRoberto Sassu .enabled = true 768c7a703eSRoberto Sassu }, 7766dbc325SMimi Zohar }; 7866dbc325SMimi Zohar 7921af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames); 8021af7663SMatthew Garrett 8132ba540fSAustin Kim static int evm_fixmode __ro_after_init; 827102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str) 837102ebcdSMimi Zohar { 847102ebcdSMimi Zohar if (strncmp(str, "fix", 3) == 0) 857102ebcdSMimi Zohar evm_fixmode = 1; 867fe2bb7eSBruno Meneguele else 877fe2bb7eSBruno Meneguele pr_err("invalid \"%s\" mode", str); 887fe2bb7eSBruno Meneguele 89f2544f5eSRandy Dunlap return 1; 907102ebcdSMimi Zohar } 917102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode); 927102ebcdSMimi Zohar 93d3b33679SDmitry Kasatkin static void __init evm_init_config(void) 94d3b33679SDmitry Kasatkin { 9521af7663SMatthew Garrett int i, xattrs; 9621af7663SMatthew Garrett 9721af7663SMatthew Garrett xattrs = ARRAY_SIZE(evm_config_default_xattrnames); 9821af7663SMatthew Garrett 9921af7663SMatthew Garrett pr_info("Initialising EVM extended attributes:\n"); 10021af7663SMatthew Garrett for (i = 0; i < xattrs; i++) { 1018c7a703eSRoberto Sassu pr_info("%s%s\n", evm_config_default_xattrnames[i].name, 1028c7a703eSRoberto Sassu !evm_config_default_xattrnames[i].enabled ? 1038c7a703eSRoberto Sassu " (disabled)" : ""); 10421af7663SMatthew Garrett list_add_tail(&evm_config_default_xattrnames[i].list, 10521af7663SMatthew Garrett &evm_config_xattrnames); 10621af7663SMatthew Garrett } 10721af7663SMatthew Garrett 108d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID 109d3b33679SDmitry Kasatkin evm_hmac_attrs |= EVM_ATTR_FSUUID; 110d3b33679SDmitry Kasatkin #endif 111d3b33679SDmitry Kasatkin pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs); 112d3b33679SDmitry Kasatkin } 113d3b33679SDmitry Kasatkin 114ae1ba167SMatthew Garrett static bool evm_key_loaded(void) 115ae1ba167SMatthew Garrett { 116ae1ba167SMatthew Garrett return (bool)(evm_initialized & EVM_KEY_MASK); 117ae1ba167SMatthew Garrett } 118ae1ba167SMatthew Garrett 1194a804b8aSRoberto Sassu /* 1204a804b8aSRoberto Sassu * This function determines whether or not it is safe to ignore verification 1214a804b8aSRoberto Sassu * errors, based on the ability of EVM to calculate HMACs. If the HMAC key 1224a804b8aSRoberto Sassu * is not loaded, and it cannot be loaded in the future due to the 1234a804b8aSRoberto Sassu * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the 1244a804b8aSRoberto Sassu * attrs/xattrs being found invalid will not make them valid. 1254a804b8aSRoberto Sassu */ 1264a804b8aSRoberto Sassu static bool evm_hmac_disabled(void) 1274a804b8aSRoberto Sassu { 1284a804b8aSRoberto Sassu if (evm_initialized & EVM_INIT_HMAC) 1294a804b8aSRoberto Sassu return false; 1304a804b8aSRoberto Sassu 1314a804b8aSRoberto Sassu if (!(evm_initialized & EVM_SETUP_COMPLETE)) 1324a804b8aSRoberto Sassu return false; 1334a804b8aSRoberto Sassu 1344a804b8aSRoberto Sassu return true; 1354a804b8aSRoberto Sassu } 1364a804b8aSRoberto Sassu 13715647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry) 13815647eb3SDmitry Kasatkin { 139c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 14021af7663SMatthew Garrett struct xattr_list *xattr; 14115647eb3SDmitry Kasatkin int error; 14215647eb3SDmitry Kasatkin int count = 0; 14315647eb3SDmitry Kasatkin 1445d6c3191SAndreas Gruenbacher if (!(inode->i_opflags & IOP_XATTR)) 14515647eb3SDmitry Kasatkin return -EOPNOTSUPP; 14615647eb3SDmitry Kasatkin 147770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 14821af7663SMatthew Garrett error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0); 14915647eb3SDmitry Kasatkin if (error < 0) { 15015647eb3SDmitry Kasatkin if (error == -ENODATA) 15115647eb3SDmitry Kasatkin continue; 15215647eb3SDmitry Kasatkin return error; 15315647eb3SDmitry Kasatkin } 15415647eb3SDmitry Kasatkin count++; 15515647eb3SDmitry Kasatkin } 15615647eb3SDmitry Kasatkin 15715647eb3SDmitry Kasatkin return count; 15815647eb3SDmitry Kasatkin } 15915647eb3SDmitry Kasatkin 16066dbc325SMimi Zohar /* 16166dbc325SMimi Zohar * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 16266dbc325SMimi Zohar * 16366dbc325SMimi Zohar * Compute the HMAC on the dentry's protected set of extended attributes 1647102ebcdSMimi Zohar * and compare it against the stored security.evm xattr. 1657102ebcdSMimi Zohar * 1667102ebcdSMimi Zohar * For performance: 1677102ebcdSMimi Zohar * - use the previoulsy retrieved xattr value and length to calculate the 16866dbc325SMimi Zohar * HMAC.) 1697102ebcdSMimi Zohar * - cache the verification result in the iint, when available. 17066dbc325SMimi Zohar * 17166dbc325SMimi Zohar * Returns integrity status 17266dbc325SMimi Zohar */ 17366dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry, 17466dbc325SMimi Zohar const char *xattr_name, 17566dbc325SMimi Zohar char *xattr_value, 17666dbc325SMimi Zohar size_t xattr_value_len, 17766dbc325SMimi Zohar struct integrity_iint_cache *iint) 17866dbc325SMimi Zohar { 17915647eb3SDmitry Kasatkin struct evm_ima_xattr_data *xattr_data = NULL; 1805feeb611SMatthew Garrett struct signature_v2_hdr *hdr; 181566be59aSMimi Zohar enum integrity_status evm_status = INTEGRITY_PASS; 1825feeb611SMatthew Garrett struct evm_digest digest; 18370946c4aSSascha Hauer struct inode *inode; 184cdef685bSRoberto Sassu int rc, xattr_len, evm_immutable = 0; 18566dbc325SMimi Zohar 18650b97748SMatthew Garrett if (iint && (iint->evm_status == INTEGRITY_PASS || 18750b97748SMatthew Garrett iint->evm_status == INTEGRITY_PASS_IMMUTABLE)) 18824e0198eSDmitry Kasatkin return iint->evm_status; 18966dbc325SMimi Zohar 1906d38ca01SDmitry Kasatkin /* if status is not PASS, try to check again - against -ENOMEM */ 1916d38ca01SDmitry Kasatkin 19215647eb3SDmitry Kasatkin /* first need to know the sig type */ 193c7c7a1a1STycho Andersen rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM, 194c7c7a1a1STycho Andersen (char **)&xattr_data, 0, GFP_NOFS); 19515647eb3SDmitry Kasatkin if (rc <= 0) { 1961f100979SDmitry Kasatkin evm_status = INTEGRITY_FAIL; 1971f100979SDmitry Kasatkin if (rc == -ENODATA) { 19815647eb3SDmitry Kasatkin rc = evm_find_protected_xattrs(dentry); 19915647eb3SDmitry Kasatkin if (rc > 0) 20015647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOLABEL; 20115647eb3SDmitry Kasatkin else if (rc == 0) 20215647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOXATTRS; /* new file */ 2031f100979SDmitry Kasatkin } else if (rc == -EOPNOTSUPP) { 2041f100979SDmitry Kasatkin evm_status = INTEGRITY_UNKNOWN; 20515647eb3SDmitry Kasatkin } 206566be59aSMimi Zohar goto out; 207566be59aSMimi Zohar } 20866dbc325SMimi Zohar 209b1aaab22SDmitry Kasatkin xattr_len = rc; 21015647eb3SDmitry Kasatkin 21115647eb3SDmitry Kasatkin /* check value type */ 21215647eb3SDmitry Kasatkin switch (xattr_data->type) { 21315647eb3SDmitry Kasatkin case EVM_XATTR_HMAC: 214650b29dbSThiago Jung Bauermann if (xattr_len != sizeof(struct evm_xattr)) { 215b4bfec7fSSeth Forshee evm_status = INTEGRITY_FAIL; 216b4bfec7fSSeth Forshee goto out; 217b4bfec7fSSeth Forshee } 2185feeb611SMatthew Garrett 2195feeb611SMatthew Garrett digest.hdr.algo = HASH_ALGO_SHA1; 22015647eb3SDmitry Kasatkin rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 2215feeb611SMatthew Garrett xattr_value_len, &digest); 22215647eb3SDmitry Kasatkin if (rc) 22315647eb3SDmitry Kasatkin break; 224650b29dbSThiago Jung Bauermann rc = crypto_memneq(xattr_data->data, digest.digest, 2255feeb611SMatthew Garrett SHA1_DIGEST_SIZE); 22615647eb3SDmitry Kasatkin if (rc) 22715647eb3SDmitry Kasatkin rc = -EINVAL; 22815647eb3SDmitry Kasatkin break; 22950b97748SMatthew Garrett case EVM_XATTR_PORTABLE_DIGSIG: 230cdef685bSRoberto Sassu evm_immutable = 1; 231cdef685bSRoberto Sassu fallthrough; 232cdef685bSRoberto Sassu case EVM_IMA_XATTR_DIGSIG: 233455b6c91SRoberto Sassu /* accept xattr with non-empty signature field */ 234455b6c91SRoberto Sassu if (xattr_len <= sizeof(struct signature_v2_hdr)) { 235455b6c91SRoberto Sassu evm_status = INTEGRITY_FAIL; 236455b6c91SRoberto Sassu goto out; 237455b6c91SRoberto Sassu } 238455b6c91SRoberto Sassu 2395feeb611SMatthew Garrett hdr = (struct signature_v2_hdr *)xattr_data; 2405feeb611SMatthew Garrett digest.hdr.algo = hdr->hash_algo; 24115647eb3SDmitry Kasatkin rc = evm_calc_hash(dentry, xattr_name, xattr_value, 2425feeb611SMatthew Garrett xattr_value_len, xattr_data->type, &digest); 24315647eb3SDmitry Kasatkin if (rc) 24415647eb3SDmitry Kasatkin break; 24515647eb3SDmitry Kasatkin rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, 246b1aaab22SDmitry Kasatkin (const char *)xattr_data, xattr_len, 2475feeb611SMatthew Garrett digest.digest, digest.hdr.length); 24815647eb3SDmitry Kasatkin if (!rc) { 24970946c4aSSascha Hauer inode = d_backing_inode(dentry); 25070946c4aSSascha Hauer 25150b97748SMatthew Garrett if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) { 25250b97748SMatthew Garrett if (iint) 25350b97748SMatthew Garrett iint->flags |= EVM_IMMUTABLE_DIGSIG; 25450b97748SMatthew Garrett evm_status = INTEGRITY_PASS_IMMUTABLE; 25570946c4aSSascha Hauer } else if (!IS_RDONLY(inode) && 25670946c4aSSascha Hauer !(inode->i_sb->s_readonly_remount) && 25770946c4aSSascha Hauer !IS_IMMUTABLE(inode)) { 258c2baec7fSDmitry Kasatkin evm_update_evmxattr(dentry, xattr_name, 259c2baec7fSDmitry Kasatkin xattr_value, 26015647eb3SDmitry Kasatkin xattr_value_len); 26115647eb3SDmitry Kasatkin } 26250b97748SMatthew Garrett } 26315647eb3SDmitry Kasatkin break; 26415647eb3SDmitry Kasatkin default: 26515647eb3SDmitry Kasatkin rc = -EINVAL; 26615647eb3SDmitry Kasatkin break; 26715647eb3SDmitry Kasatkin } 26815647eb3SDmitry Kasatkin 269cdef685bSRoberto Sassu if (rc) { 270cdef685bSRoberto Sassu if (rc == -ENODATA) 271cdef685bSRoberto Sassu evm_status = INTEGRITY_NOXATTRS; 272cdef685bSRoberto Sassu else if (evm_immutable) 273cdef685bSRoberto Sassu evm_status = INTEGRITY_FAIL_IMMUTABLE; 274cdef685bSRoberto Sassu else 275cdef685bSRoberto Sassu evm_status = INTEGRITY_FAIL; 276cdef685bSRoberto Sassu } 27787ac3d00SMimi Zohar pr_debug("digest: (%d) [%*phN]\n", digest.hdr.length, digest.hdr.length, 27887ac3d00SMimi Zohar digest.digest); 2797102ebcdSMimi Zohar out: 2807102ebcdSMimi Zohar if (iint) 2817102ebcdSMimi Zohar iint->evm_status = evm_status; 28215647eb3SDmitry Kasatkin kfree(xattr_data); 2837102ebcdSMimi Zohar return evm_status; 28466dbc325SMimi Zohar } 28566dbc325SMimi Zohar 2868c7a703eSRoberto Sassu static int evm_protected_xattr_common(const char *req_xattr_name, 2878c7a703eSRoberto Sassu bool all_xattrs) 28866dbc325SMimi Zohar { 28966dbc325SMimi Zohar int namelen; 29066dbc325SMimi Zohar int found = 0; 29121af7663SMatthew Garrett struct xattr_list *xattr; 29266dbc325SMimi Zohar 29366dbc325SMimi Zohar namelen = strlen(req_xattr_name); 294770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 2958c7a703eSRoberto Sassu if (!all_xattrs && !xattr->enabled) 2968c7a703eSRoberto Sassu continue; 2978c7a703eSRoberto Sassu 29821af7663SMatthew Garrett if ((strlen(xattr->name) == namelen) 29921af7663SMatthew Garrett && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) { 30066dbc325SMimi Zohar found = 1; 30166dbc325SMimi Zohar break; 30266dbc325SMimi Zohar } 303cb723180SMimi Zohar if (strncmp(req_xattr_name, 30421af7663SMatthew Garrett xattr->name + XATTR_SECURITY_PREFIX_LEN, 305cb723180SMimi Zohar strlen(req_xattr_name)) == 0) { 306cb723180SMimi Zohar found = 1; 307cb723180SMimi Zohar break; 308cb723180SMimi Zohar } 30966dbc325SMimi Zohar } 31021af7663SMatthew Garrett 31166dbc325SMimi Zohar return found; 31266dbc325SMimi Zohar } 31366dbc325SMimi Zohar 3148c7a703eSRoberto Sassu static int evm_protected_xattr(const char *req_xattr_name) 3158c7a703eSRoberto Sassu { 3168c7a703eSRoberto Sassu return evm_protected_xattr_common(req_xattr_name, false); 3178c7a703eSRoberto Sassu } 3188c7a703eSRoberto Sassu 3198c7a703eSRoberto Sassu int evm_protected_xattr_if_enabled(const char *req_xattr_name) 3208c7a703eSRoberto Sassu { 3218c7a703eSRoberto Sassu return evm_protected_xattr_common(req_xattr_name, true); 3228c7a703eSRoberto Sassu } 3238c7a703eSRoberto Sassu 32466dbc325SMimi Zohar /** 3258314b673SRoberto Sassu * evm_read_protected_xattrs - read EVM protected xattr names, lengths, values 3268314b673SRoberto Sassu * @dentry: dentry of the read xattrs 3278314b673SRoberto Sassu * @inode: inode of the read xattrs 3288314b673SRoberto Sassu * @buffer: buffer xattr names, lengths or values are copied to 3298314b673SRoberto Sassu * @buffer_size: size of buffer 3308314b673SRoberto Sassu * @type: n: names, l: lengths, v: values 3318314b673SRoberto Sassu * @canonical_fmt: data format (true: little endian, false: native format) 3328314b673SRoberto Sassu * 3338314b673SRoberto Sassu * Read protected xattr names (separated by |), lengths (u32) or values for a 3348314b673SRoberto Sassu * given dentry and return the total size of copied data. If buffer is NULL, 3358314b673SRoberto Sassu * just return the total size. 3368314b673SRoberto Sassu * 3378314b673SRoberto Sassu * Returns the total size on success, a negative value on error. 3388314b673SRoberto Sassu */ 3398314b673SRoberto Sassu int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, 3408314b673SRoberto Sassu int buffer_size, char type, bool canonical_fmt) 3418314b673SRoberto Sassu { 3428314b673SRoberto Sassu struct xattr_list *xattr; 3438314b673SRoberto Sassu int rc, size, total_size = 0; 3448314b673SRoberto Sassu 3458314b673SRoberto Sassu list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 3468314b673SRoberto Sassu rc = __vfs_getxattr(dentry, d_backing_inode(dentry), 3478314b673SRoberto Sassu xattr->name, NULL, 0); 3488314b673SRoberto Sassu if (rc < 0 && rc == -ENODATA) 3498314b673SRoberto Sassu continue; 3508314b673SRoberto Sassu else if (rc < 0) 3518314b673SRoberto Sassu return rc; 3528314b673SRoberto Sassu 3538314b673SRoberto Sassu switch (type) { 3548314b673SRoberto Sassu case 'n': 3558314b673SRoberto Sassu size = strlen(xattr->name) + 1; 3568314b673SRoberto Sassu if (buffer) { 3578314b673SRoberto Sassu if (total_size) 3588314b673SRoberto Sassu *(buffer + total_size - 1) = '|'; 3598314b673SRoberto Sassu 3608314b673SRoberto Sassu memcpy(buffer + total_size, xattr->name, size); 3618314b673SRoberto Sassu } 3628314b673SRoberto Sassu break; 3638314b673SRoberto Sassu case 'l': 3648314b673SRoberto Sassu size = sizeof(u32); 3658314b673SRoberto Sassu if (buffer) { 3668314b673SRoberto Sassu if (canonical_fmt) 3676b26285fSRoberto Sassu rc = (__force int)cpu_to_le32(rc); 3688314b673SRoberto Sassu 3698314b673SRoberto Sassu *(u32 *)(buffer + total_size) = rc; 3708314b673SRoberto Sassu } 3718314b673SRoberto Sassu break; 3728314b673SRoberto Sassu case 'v': 3738314b673SRoberto Sassu size = rc; 3748314b673SRoberto Sassu if (buffer) { 3758314b673SRoberto Sassu rc = __vfs_getxattr(dentry, 3768314b673SRoberto Sassu d_backing_inode(dentry), xattr->name, 3778314b673SRoberto Sassu buffer + total_size, 3788314b673SRoberto Sassu buffer_size - total_size); 3798314b673SRoberto Sassu if (rc < 0) 3808314b673SRoberto Sassu return rc; 3818314b673SRoberto Sassu } 3828314b673SRoberto Sassu break; 3838314b673SRoberto Sassu default: 3848314b673SRoberto Sassu return -EINVAL; 3858314b673SRoberto Sassu } 3868314b673SRoberto Sassu 3878314b673SRoberto Sassu total_size += size; 3888314b673SRoberto Sassu } 3898314b673SRoberto Sassu 3908314b673SRoberto Sassu return total_size; 3918314b673SRoberto Sassu } 3928314b673SRoberto Sassu 3938314b673SRoberto Sassu /** 39466dbc325SMimi Zohar * evm_verifyxattr - verify the integrity of the requested xattr 39566dbc325SMimi Zohar * @dentry: object of the verify xattr 39666dbc325SMimi Zohar * @xattr_name: requested xattr 39766dbc325SMimi Zohar * @xattr_value: requested xattr value 39866dbc325SMimi Zohar * @xattr_value_len: requested xattr value length 39966dbc325SMimi Zohar * 40066dbc325SMimi Zohar * Calculate the HMAC for the given dentry and verify it against the stored 40166dbc325SMimi Zohar * security.evm xattr. For performance, use the xattr value and length 40266dbc325SMimi Zohar * previously retrieved to calculate the HMAC. 40366dbc325SMimi Zohar * 40466dbc325SMimi Zohar * Returns the xattr integrity status. 40566dbc325SMimi Zohar * 40666dbc325SMimi Zohar * This function requires the caller to lock the inode's i_mutex before it 40766dbc325SMimi Zohar * is executed. 40866dbc325SMimi Zohar */ 40966dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry, 41066dbc325SMimi Zohar const char *xattr_name, 4112960e6cbSDmitry Kasatkin void *xattr_value, size_t xattr_value_len, 4122960e6cbSDmitry Kasatkin struct integrity_iint_cache *iint) 41366dbc325SMimi Zohar { 414ae1ba167SMatthew Garrett if (!evm_key_loaded() || !evm_protected_xattr(xattr_name)) 41566dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 41666dbc325SMimi Zohar 4172960e6cbSDmitry Kasatkin if (!iint) { 418c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 41966dbc325SMimi Zohar if (!iint) 42066dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 4212960e6cbSDmitry Kasatkin } 4222960e6cbSDmitry Kasatkin return evm_verify_hmac(dentry, xattr_name, xattr_value, 42366dbc325SMimi Zohar xattr_value_len, iint); 42466dbc325SMimi Zohar } 42566dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr); 42666dbc325SMimi Zohar 42766dbc325SMimi Zohar /* 4287102ebcdSMimi Zohar * evm_verify_current_integrity - verify the dentry's metadata integrity 4297102ebcdSMimi Zohar * @dentry: pointer to the affected dentry 4307102ebcdSMimi Zohar * 4317102ebcdSMimi Zohar * Verify and return the dentry's metadata integrity. The exceptions are 4327102ebcdSMimi Zohar * before EVM is initialized or in 'fix' mode. 4337102ebcdSMimi Zohar */ 4347102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) 4357102ebcdSMimi Zohar { 436c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 4377102ebcdSMimi Zohar 438ae1ba167SMatthew Garrett if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) 439e11afdbbSStefan Berger return INTEGRITY_PASS; 4407102ebcdSMimi Zohar return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 4417102ebcdSMimi Zohar } 4427102ebcdSMimi Zohar 443a924ce0bSMimi Zohar /* 4441886ab01SRoberto Sassu * evm_xattr_acl_change - check if passed ACL changes the inode mode 4451886ab01SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 4461886ab01SRoberto Sassu * @dentry: pointer to the affected dentry 4471886ab01SRoberto Sassu * @xattr_name: requested xattr 4481886ab01SRoberto Sassu * @xattr_value: requested xattr value 4491886ab01SRoberto Sassu * @xattr_value_len: requested xattr value length 4501886ab01SRoberto Sassu * 4511886ab01SRoberto Sassu * Check if passed ACL changes the inode mode, which is protected by EVM. 4521886ab01SRoberto Sassu * 4531886ab01SRoberto Sassu * Returns 1 if passed ACL causes inode mode change, 0 otherwise. 4541886ab01SRoberto Sassu */ 4551886ab01SRoberto Sassu static int evm_xattr_acl_change(struct user_namespace *mnt_userns, 4561886ab01SRoberto Sassu struct dentry *dentry, const char *xattr_name, 4571886ab01SRoberto Sassu const void *xattr_value, size_t xattr_value_len) 4581886ab01SRoberto Sassu { 4591886ab01SRoberto Sassu #ifdef CONFIG_FS_POSIX_ACL 4601886ab01SRoberto Sassu umode_t mode; 4611886ab01SRoberto Sassu struct posix_acl *acl = NULL, *acl_res; 4621886ab01SRoberto Sassu struct inode *inode = d_backing_inode(dentry); 4631886ab01SRoberto Sassu int rc; 4641886ab01SRoberto Sassu 4651886ab01SRoberto Sassu /* 4661886ab01SRoberto Sassu * user_ns is not relevant here, ACL_USER/ACL_GROUP don't have impact 4671886ab01SRoberto Sassu * on the inode mode (see posix_acl_equiv_mode()). 4681886ab01SRoberto Sassu */ 4691886ab01SRoberto Sassu acl = posix_acl_from_xattr(&init_user_ns, xattr_value, xattr_value_len); 4701886ab01SRoberto Sassu if (IS_ERR_OR_NULL(acl)) 4711886ab01SRoberto Sassu return 1; 4721886ab01SRoberto Sassu 4731886ab01SRoberto Sassu acl_res = acl; 4741886ab01SRoberto Sassu /* 4751886ab01SRoberto Sassu * Passing mnt_userns is necessary to correctly determine the GID in 4761886ab01SRoberto Sassu * an idmapped mount, as the GID is used to clear the setgid bit in 4771886ab01SRoberto Sassu * the inode mode. 4781886ab01SRoberto Sassu */ 4791886ab01SRoberto Sassu rc = posix_acl_update_mode(mnt_userns, inode, &mode, &acl_res); 4801886ab01SRoberto Sassu 4811886ab01SRoberto Sassu posix_acl_release(acl); 4821886ab01SRoberto Sassu 4831886ab01SRoberto Sassu if (rc) 4841886ab01SRoberto Sassu return 1; 4851886ab01SRoberto Sassu 4861886ab01SRoberto Sassu if (inode->i_mode != mode) 4871886ab01SRoberto Sassu return 1; 4881886ab01SRoberto Sassu #endif 4891886ab01SRoberto Sassu return 0; 4901886ab01SRoberto Sassu } 4911886ab01SRoberto Sassu 4921886ab01SRoberto Sassu /* 4931886ab01SRoberto Sassu * evm_xattr_change - check if passed xattr value differs from current value 4941886ab01SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 4951886ab01SRoberto Sassu * @dentry: pointer to the affected dentry 4961886ab01SRoberto Sassu * @xattr_name: requested xattr 4971886ab01SRoberto Sassu * @xattr_value: requested xattr value 4981886ab01SRoberto Sassu * @xattr_value_len: requested xattr value length 4991886ab01SRoberto Sassu * 5001886ab01SRoberto Sassu * Check if passed xattr value differs from current value. 5011886ab01SRoberto Sassu * 5021886ab01SRoberto Sassu * Returns 1 if passed xattr value differs from current value, 0 otherwise. 5031886ab01SRoberto Sassu */ 5041886ab01SRoberto Sassu static int evm_xattr_change(struct user_namespace *mnt_userns, 5051886ab01SRoberto Sassu struct dentry *dentry, const char *xattr_name, 5061886ab01SRoberto Sassu const void *xattr_value, size_t xattr_value_len) 5071886ab01SRoberto Sassu { 5081886ab01SRoberto Sassu char *xattr_data = NULL; 5091886ab01SRoberto Sassu int rc = 0; 5101886ab01SRoberto Sassu 5111886ab01SRoberto Sassu if (posix_xattr_acl(xattr_name)) 5121886ab01SRoberto Sassu return evm_xattr_acl_change(mnt_userns, dentry, xattr_name, 5131886ab01SRoberto Sassu xattr_value, xattr_value_len); 5141886ab01SRoberto Sassu 5151886ab01SRoberto Sassu rc = vfs_getxattr_alloc(&init_user_ns, dentry, xattr_name, &xattr_data, 5161886ab01SRoberto Sassu 0, GFP_NOFS); 5171886ab01SRoberto Sassu if (rc < 0) 5181886ab01SRoberto Sassu return 1; 5191886ab01SRoberto Sassu 5201886ab01SRoberto Sassu if (rc == xattr_value_len) 5211886ab01SRoberto Sassu rc = !!memcmp(xattr_value, xattr_data, rc); 5221886ab01SRoberto Sassu else 5231886ab01SRoberto Sassu rc = 1; 5241886ab01SRoberto Sassu 5251886ab01SRoberto Sassu kfree(xattr_data); 5261886ab01SRoberto Sassu return rc; 5271886ab01SRoberto Sassu } 5281886ab01SRoberto Sassu 5291886ab01SRoberto Sassu /* 530a924ce0bSMimi Zohar * evm_protect_xattr - protect the EVM extended attribute 531a924ce0bSMimi Zohar * 532bf6d0f5dSMimi Zohar * Prevent security.evm from being modified or removed without the 533bf6d0f5dSMimi Zohar * necessary permissions or when the existing value is invalid. 534bf6d0f5dSMimi Zohar * 535bf6d0f5dSMimi Zohar * The posix xattr acls are 'system' prefixed, which normally would not 536bf6d0f5dSMimi Zohar * affect security.evm. An interesting side affect of writing posix xattr 537bf6d0f5dSMimi Zohar * acls is their modifying of the i_mode, which is included in security.evm. 538bf6d0f5dSMimi Zohar * For posix xattr acls only, permit security.evm, even if it currently 53950b97748SMatthew Garrett * doesn't exist, to be updated unless the EVM signature is immutable. 540a924ce0bSMimi Zohar */ 5417e135dc7SRoberto Sassu static int evm_protect_xattr(struct user_namespace *mnt_userns, 5427e135dc7SRoberto Sassu struct dentry *dentry, const char *xattr_name, 543a924ce0bSMimi Zohar const void *xattr_value, size_t xattr_value_len) 544a924ce0bSMimi Zohar { 545a924ce0bSMimi Zohar enum integrity_status evm_status; 546a924ce0bSMimi Zohar 547a924ce0bSMimi Zohar if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 548a924ce0bSMimi Zohar if (!capable(CAP_SYS_ADMIN)) 549a924ce0bSMimi Zohar return -EPERM; 550bf6d0f5dSMimi Zohar } else if (!evm_protected_xattr(xattr_name)) { 551bf6d0f5dSMimi Zohar if (!posix_xattr_acl(xattr_name)) 552a924ce0bSMimi Zohar return 0; 553bf6d0f5dSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 554bf6d0f5dSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 555566be59aSMimi Zohar (evm_status == INTEGRITY_NOXATTRS)) 556bf6d0f5dSMimi Zohar return 0; 5579b97b6cdSMimi Zohar goto out; 558bf6d0f5dSMimi Zohar } 559ae1ba167SMatthew Garrett 560a924ce0bSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 5613dcbad52SDmitry Kasatkin if (evm_status == INTEGRITY_NOXATTRS) { 5623dcbad52SDmitry Kasatkin struct integrity_iint_cache *iint; 5633dcbad52SDmitry Kasatkin 5644a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 5654a804b8aSRoberto Sassu if (evm_hmac_disabled()) 5664a804b8aSRoberto Sassu return 0; 5674a804b8aSRoberto Sassu 568c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 5693dcbad52SDmitry Kasatkin if (iint && (iint->flags & IMA_NEW_FILE)) 5703dcbad52SDmitry Kasatkin return 0; 5715101a185SMimi Zohar 5725101a185SMimi Zohar /* exception for pseudo filesystems */ 573fc64005cSAl Viro if (dentry->d_sb->s_magic == TMPFS_MAGIC 574fc64005cSAl Viro || dentry->d_sb->s_magic == SYSFS_MAGIC) 5755101a185SMimi Zohar return 0; 5765101a185SMimi Zohar 5775101a185SMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_METADATA, 5785101a185SMimi Zohar dentry->d_inode, dentry->d_name.name, 5795101a185SMimi Zohar "update_metadata", 5805101a185SMimi Zohar integrity_status_msg[evm_status], 5815101a185SMimi Zohar -EPERM, 0); 5823dcbad52SDmitry Kasatkin } 5839b97b6cdSMimi Zohar out: 5844a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 5854a804b8aSRoberto Sassu if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 5864a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN)) 5874a804b8aSRoberto Sassu return 0; 588cdef685bSRoberto Sassu 589cdef685bSRoberto Sassu /* 590cdef685bSRoberto Sassu * Writing other xattrs is safe for portable signatures, as portable 591cdef685bSRoberto Sassu * signatures are immutable and can never be updated. 592cdef685bSRoberto Sassu */ 593cdef685bSRoberto Sassu if (evm_status == INTEGRITY_FAIL_IMMUTABLE) 594cdef685bSRoberto Sassu return 0; 595cdef685bSRoberto Sassu 5961886ab01SRoberto Sassu if (evm_status == INTEGRITY_PASS_IMMUTABLE && 5971886ab01SRoberto Sassu !evm_xattr_change(mnt_userns, dentry, xattr_name, xattr_value, 5981886ab01SRoberto Sassu xattr_value_len)) 5991886ab01SRoberto Sassu return 0; 6001886ab01SRoberto Sassu 6011886ab01SRoberto Sassu if (evm_status != INTEGRITY_PASS && 6021886ab01SRoberto Sassu evm_status != INTEGRITY_PASS_IMMUTABLE) 603c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 6049b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 6059b97b6cdSMimi Zohar integrity_status_msg[evm_status], 6069b97b6cdSMimi Zohar -EPERM, 0); 607a924ce0bSMimi Zohar return evm_status == INTEGRITY_PASS ? 0 : -EPERM; 608a924ce0bSMimi Zohar } 609a924ce0bSMimi Zohar 61066dbc325SMimi Zohar /** 61166dbc325SMimi Zohar * evm_inode_setxattr - protect the EVM extended attribute 6127e135dc7SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 61366dbc325SMimi Zohar * @dentry: pointer to the affected dentry 61466dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 61566dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 61666dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 61766dbc325SMimi Zohar * 6182fb1c9a4SMimi Zohar * Before allowing the 'security.evm' protected xattr to be updated, 6192fb1c9a4SMimi Zohar * verify the existing value is valid. As only the kernel should have 6202fb1c9a4SMimi Zohar * access to the EVM encrypted key needed to calculate the HMAC, prevent 6212fb1c9a4SMimi Zohar * userspace from writing HMAC value. Writing 'security.evm' requires 6222fb1c9a4SMimi Zohar * requires CAP_SYS_ADMIN privileges. 62366dbc325SMimi Zohar */ 6247e135dc7SRoberto Sassu int evm_inode_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry, 6257e135dc7SRoberto Sassu const char *xattr_name, const void *xattr_value, 6267e135dc7SRoberto Sassu size_t xattr_value_len) 62766dbc325SMimi Zohar { 6282fb1c9a4SMimi Zohar const struct evm_ima_xattr_data *xattr_data = xattr_value; 6292fb1c9a4SMimi Zohar 630ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 631ae1ba167SMatthew Garrett * there's no HMAC key loaded 632ae1ba167SMatthew Garrett */ 633ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 634ae1ba167SMatthew Garrett return 0; 635ae1ba167SMatthew Garrett 6363b1deef6SDmitry Kasatkin if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 6373b1deef6SDmitry Kasatkin if (!xattr_value_len) 6383b1deef6SDmitry Kasatkin return -EINVAL; 63950b97748SMatthew Garrett if (xattr_data->type != EVM_IMA_XATTR_DIGSIG && 64050b97748SMatthew Garrett xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) 6412fb1c9a4SMimi Zohar return -EPERM; 6423b1deef6SDmitry Kasatkin } 6437e135dc7SRoberto Sassu return evm_protect_xattr(mnt_userns, dentry, xattr_name, xattr_value, 64466dbc325SMimi Zohar xattr_value_len); 64566dbc325SMimi Zohar } 64666dbc325SMimi Zohar 64766dbc325SMimi Zohar /** 64866dbc325SMimi Zohar * evm_inode_removexattr - protect the EVM extended attribute 6497e135dc7SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 65066dbc325SMimi Zohar * @dentry: pointer to the affected dentry 65166dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 65266dbc325SMimi Zohar * 6537102ebcdSMimi Zohar * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that 6547102ebcdSMimi Zohar * the current value is valid. 65566dbc325SMimi Zohar */ 6567e135dc7SRoberto Sassu int evm_inode_removexattr(struct user_namespace *mnt_userns, 6577e135dc7SRoberto Sassu struct dentry *dentry, const char *xattr_name) 65866dbc325SMimi Zohar { 659ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 660ae1ba167SMatthew Garrett * there's no HMAC key loaded 661ae1ba167SMatthew Garrett */ 662ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 663ae1ba167SMatthew Garrett return 0; 664ae1ba167SMatthew Garrett 6657e135dc7SRoberto Sassu return evm_protect_xattr(mnt_userns, dentry, xattr_name, NULL, 0); 66666dbc325SMimi Zohar } 66766dbc325SMimi Zohar 668523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode) 669523b74b1SDmitry Kasatkin { 670523b74b1SDmitry Kasatkin struct integrity_iint_cache *iint; 671523b74b1SDmitry Kasatkin 672523b74b1SDmitry Kasatkin iint = integrity_iint_find(inode); 673523b74b1SDmitry Kasatkin if (iint) 674523b74b1SDmitry Kasatkin iint->evm_status = INTEGRITY_UNKNOWN; 675523b74b1SDmitry Kasatkin } 676523b74b1SDmitry Kasatkin 67766dbc325SMimi Zohar /** 678e3ccfe1aSRoberto Sassu * evm_revalidate_status - report whether EVM status re-validation is necessary 679e3ccfe1aSRoberto Sassu * @xattr_name: pointer to the affected extended attribute name 680e3ccfe1aSRoberto Sassu * 681e3ccfe1aSRoberto Sassu * Report whether callers of evm_verifyxattr() should re-validate the 682e3ccfe1aSRoberto Sassu * EVM status. 683e3ccfe1aSRoberto Sassu * 684e3ccfe1aSRoberto Sassu * Return true if re-validation is necessary, false otherwise. 685e3ccfe1aSRoberto Sassu */ 686e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name) 687e3ccfe1aSRoberto Sassu { 688e3ccfe1aSRoberto Sassu if (!evm_key_loaded()) 689e3ccfe1aSRoberto Sassu return false; 690e3ccfe1aSRoberto Sassu 691e3ccfe1aSRoberto Sassu /* evm_inode_post_setattr() passes NULL */ 692e3ccfe1aSRoberto Sassu if (!xattr_name) 693e3ccfe1aSRoberto Sassu return true; 694e3ccfe1aSRoberto Sassu 695e3ccfe1aSRoberto Sassu if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) && 696e3ccfe1aSRoberto Sassu strcmp(xattr_name, XATTR_NAME_EVM)) 697e3ccfe1aSRoberto Sassu return false; 698e3ccfe1aSRoberto Sassu 699e3ccfe1aSRoberto Sassu return true; 700e3ccfe1aSRoberto Sassu } 701e3ccfe1aSRoberto Sassu 702e3ccfe1aSRoberto Sassu /** 70366dbc325SMimi Zohar * evm_inode_post_setxattr - update 'security.evm' to reflect the changes 70466dbc325SMimi Zohar * @dentry: pointer to the affected dentry 70566dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 70666dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 70766dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 70866dbc325SMimi Zohar * 70966dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect the change. 71066dbc325SMimi Zohar * 71166dbc325SMimi Zohar * No need to take the i_mutex lock here, as this function is called from 71266dbc325SMimi Zohar * __vfs_setxattr_noperm(). The caller of which has taken the inode's 71366dbc325SMimi Zohar * i_mutex lock. 71466dbc325SMimi Zohar */ 71566dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, 71666dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 71766dbc325SMimi Zohar { 718e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 71966dbc325SMimi Zohar return; 72066dbc325SMimi Zohar 721523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 722523b74b1SDmitry Kasatkin 723e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 724e3ccfe1aSRoberto Sassu return; 725e3ccfe1aSRoberto Sassu 7264a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 7274a804b8aSRoberto Sassu return; 7284a804b8aSRoberto Sassu 72966dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); 73066dbc325SMimi Zohar } 73166dbc325SMimi Zohar 73266dbc325SMimi Zohar /** 73366dbc325SMimi Zohar * evm_inode_post_removexattr - update 'security.evm' after removing the xattr 73466dbc325SMimi Zohar * @dentry: pointer to the affected dentry 73566dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 73666dbc325SMimi Zohar * 73766dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. 7387c51bb00SDmitry Kasatkin * 7397c51bb00SDmitry Kasatkin * No need to take the i_mutex lock here, as this function is called from 7407c51bb00SDmitry Kasatkin * vfs_removexattr() which takes the i_mutex. 74166dbc325SMimi Zohar */ 74266dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) 74366dbc325SMimi Zohar { 744e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 74566dbc325SMimi Zohar return; 74666dbc325SMimi Zohar 747523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 748523b74b1SDmitry Kasatkin 749e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 750e3ccfe1aSRoberto Sassu return; 751e3ccfe1aSRoberto Sassu 7524a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 7534a804b8aSRoberto Sassu return; 7544a804b8aSRoberto Sassu 75566dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, NULL, 0); 75666dbc325SMimi Zohar } 75766dbc325SMimi Zohar 758*0e363cf3SChristian Brauner static int evm_attr_change(struct user_namespace *mnt_userns, 759*0e363cf3SChristian Brauner struct dentry *dentry, struct iattr *attr) 7601886ab01SRoberto Sassu { 7611886ab01SRoberto Sassu struct inode *inode = d_backing_inode(dentry); 7621886ab01SRoberto Sassu unsigned int ia_valid = attr->ia_valid; 7631886ab01SRoberto Sassu 76435faf310SChristian Brauner if (!i_uid_needs_update(&init_user_ns, attr, inode) && 76535faf310SChristian Brauner !i_gid_needs_update(&init_user_ns, attr, inode) && 7661886ab01SRoberto Sassu (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode)) 7671886ab01SRoberto Sassu return 0; 7681886ab01SRoberto Sassu 7691886ab01SRoberto Sassu return 1; 7701886ab01SRoberto Sassu } 7711886ab01SRoberto Sassu 77266dbc325SMimi Zohar /** 773817b54aaSMimi Zohar * evm_inode_setattr - prevent updating an invalid EVM extended attribute 774817b54aaSMimi Zohar * @dentry: pointer to the affected dentry 77550b97748SMatthew Garrett * 77650b97748SMatthew Garrett * Permit update of file attributes when files have a valid EVM signature, 77750b97748SMatthew Garrett * except in the case of them having an immutable portable signature. 778817b54aaSMimi Zohar */ 779*0e363cf3SChristian Brauner int evm_inode_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, 780*0e363cf3SChristian Brauner struct iattr *attr) 781817b54aaSMimi Zohar { 782817b54aaSMimi Zohar unsigned int ia_valid = attr->ia_valid; 783817b54aaSMimi Zohar enum integrity_status evm_status; 784817b54aaSMimi Zohar 785ae1ba167SMatthew Garrett /* Policy permits modification of the protected attrs even though 786ae1ba167SMatthew Garrett * there's no HMAC key loaded 787ae1ba167SMatthew Garrett */ 788ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 789ae1ba167SMatthew Garrett return 0; 790ae1ba167SMatthew Garrett 791a924ce0bSMimi Zohar if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))) 792817b54aaSMimi Zohar return 0; 793817b54aaSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 794cdef685bSRoberto Sassu /* 795cdef685bSRoberto Sassu * Writing attrs is safe for portable signatures, as portable signatures 796cdef685bSRoberto Sassu * are immutable and can never be updated. 797cdef685bSRoberto Sassu */ 798566be59aSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 7994a804b8aSRoberto Sassu (evm_status == INTEGRITY_NOXATTRS) || 800cdef685bSRoberto Sassu (evm_status == INTEGRITY_FAIL_IMMUTABLE) || 8014a804b8aSRoberto Sassu (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 8024a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN))) 803566be59aSMimi Zohar return 0; 8041886ab01SRoberto Sassu 8051886ab01SRoberto Sassu if (evm_status == INTEGRITY_PASS_IMMUTABLE && 806*0e363cf3SChristian Brauner !evm_attr_change(mnt_userns, dentry, attr)) 8071886ab01SRoberto Sassu return 0; 8081886ab01SRoberto Sassu 809c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 8109b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 8119b97b6cdSMimi Zohar integrity_status_msg[evm_status], -EPERM, 0); 812566be59aSMimi Zohar return -EPERM; 813817b54aaSMimi Zohar } 814817b54aaSMimi Zohar 815817b54aaSMimi Zohar /** 81666dbc325SMimi Zohar * evm_inode_post_setattr - update 'security.evm' after modifying metadata 81766dbc325SMimi Zohar * @dentry: pointer to the affected dentry 81866dbc325SMimi Zohar * @ia_valid: for the UID and GID status 81966dbc325SMimi Zohar * 82066dbc325SMimi Zohar * For now, update the HMAC stored in 'security.evm' to reflect UID/GID 82166dbc325SMimi Zohar * changes. 82266dbc325SMimi Zohar * 82366dbc325SMimi Zohar * This function is called from notify_change(), which expects the caller 82466dbc325SMimi Zohar * to lock the inode's i_mutex. 82566dbc325SMimi Zohar */ 82666dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) 82766dbc325SMimi Zohar { 828e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(NULL)) 82966dbc325SMimi Zohar return; 83066dbc325SMimi Zohar 831e3ccfe1aSRoberto Sassu evm_reset_status(dentry->d_inode); 832e3ccfe1aSRoberto Sassu 8334a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 8344a804b8aSRoberto Sassu return; 8354a804b8aSRoberto Sassu 83666dbc325SMimi Zohar if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) 83766dbc325SMimi Zohar evm_update_evmxattr(dentry, NULL, NULL, 0); 83866dbc325SMimi Zohar } 83966dbc325SMimi Zohar 840cb723180SMimi Zohar /* 8419eea2904SRoberto Sassu * evm_inode_init_security - initializes security.evm HMAC value 842cb723180SMimi Zohar */ 843cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode, 844cb723180SMimi Zohar const struct xattr *lsm_xattr, 845cb723180SMimi Zohar struct xattr *evm_xattr) 846cb723180SMimi Zohar { 847650b29dbSThiago Jung Bauermann struct evm_xattr *xattr_data; 848cb723180SMimi Zohar int rc; 849cb723180SMimi Zohar 8509eea2904SRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC) || 8519eea2904SRoberto Sassu !evm_protected_xattr(lsm_xattr->name)) 8525a4730baSMimi Zohar return 0; 853cb723180SMimi Zohar 854cb723180SMimi Zohar xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); 855cb723180SMimi Zohar if (!xattr_data) 856cb723180SMimi Zohar return -ENOMEM; 857cb723180SMimi Zohar 858650b29dbSThiago Jung Bauermann xattr_data->data.type = EVM_XATTR_HMAC; 859cb723180SMimi Zohar rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); 860cb723180SMimi Zohar if (rc < 0) 861cb723180SMimi Zohar goto out; 862cb723180SMimi Zohar 863cb723180SMimi Zohar evm_xattr->value = xattr_data; 864cb723180SMimi Zohar evm_xattr->value_len = sizeof(*xattr_data); 8659548906bSTetsuo Handa evm_xattr->name = XATTR_EVM_SUFFIX; 866cb723180SMimi Zohar return 0; 867cb723180SMimi Zohar out: 868cb723180SMimi Zohar kfree(xattr_data); 869cb723180SMimi Zohar return rc; 870cb723180SMimi Zohar } 871cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security); 872cb723180SMimi Zohar 8732ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509 8742ce523ebSDmitry Kasatkin void __init evm_load_x509(void) 8752ce523ebSDmitry Kasatkin { 87626ddabfeSDmitry Kasatkin int rc; 87726ddabfeSDmitry Kasatkin 87826ddabfeSDmitry Kasatkin rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH); 87926ddabfeSDmitry Kasatkin if (!rc) 88026ddabfeSDmitry Kasatkin evm_initialized |= EVM_INIT_X509; 8812ce523ebSDmitry Kasatkin } 8822ce523ebSDmitry Kasatkin #endif 8832ce523ebSDmitry Kasatkin 88466dbc325SMimi Zohar static int __init init_evm(void) 88566dbc325SMimi Zohar { 88666dbc325SMimi Zohar int error; 88721af7663SMatthew Garrett struct list_head *pos, *q; 88866dbc325SMimi Zohar 889d3b33679SDmitry Kasatkin evm_init_config(); 890d3b33679SDmitry Kasatkin 891f4dc3778SDmitry Kasatkin error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); 892f4dc3778SDmitry Kasatkin if (error) 89321af7663SMatthew Garrett goto error; 894f4dc3778SDmitry Kasatkin 89566dbc325SMimi Zohar error = evm_init_secfs(); 89666dbc325SMimi Zohar if (error < 0) { 89720ee451fSJoe Perches pr_info("Error registering secfs\n"); 89821af7663SMatthew Garrett goto error; 89921af7663SMatthew Garrett } 90021af7663SMatthew Garrett 90121af7663SMatthew Garrett error: 90221af7663SMatthew Garrett if (error != 0) { 90321af7663SMatthew Garrett if (!list_empty(&evm_config_xattrnames)) { 904c8b37524SYueHaibing list_for_each_safe(pos, q, &evm_config_xattrnames) 90521af7663SMatthew Garrett list_del(pos); 90621af7663SMatthew Garrett } 90721af7663SMatthew Garrett } 90821af7663SMatthew Garrett 909f4dc3778SDmitry Kasatkin return error; 91066dbc325SMimi Zohar } 91115647eb3SDmitry Kasatkin 91266dbc325SMimi Zohar late_initcall(init_evm); 913