166dbc325SMimi Zohar /* 266dbc325SMimi Zohar * Copyright (C) 2005-2010 IBM Corporation 366dbc325SMimi Zohar * 466dbc325SMimi Zohar * Author: 566dbc325SMimi Zohar * Mimi Zohar <zohar@us.ibm.com> 666dbc325SMimi Zohar * Kylene Hall <kjhall@us.ibm.com> 766dbc325SMimi Zohar * 866dbc325SMimi Zohar * This program is free software; you can redistribute it and/or modify 966dbc325SMimi Zohar * it under the terms of the GNU General Public License as published by 1066dbc325SMimi Zohar * the Free Software Foundation, version 2 of the License. 1166dbc325SMimi Zohar * 1266dbc325SMimi Zohar * File: evm_main.c 1366dbc325SMimi Zohar * implements evm_inode_setxattr, evm_inode_post_setxattr, 1466dbc325SMimi Zohar * evm_inode_removexattr, and evm_verifyxattr 1566dbc325SMimi Zohar */ 1666dbc325SMimi Zohar 1720ee451fSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1820ee451fSJoe Perches 1966dbc325SMimi Zohar #include <linux/module.h> 2066dbc325SMimi Zohar #include <linux/crypto.h> 219b97b6cdSMimi Zohar #include <linux/audit.h> 2266dbc325SMimi Zohar #include <linux/xattr.h> 2366dbc325SMimi Zohar #include <linux/integrity.h> 243e1be52dSMimi Zohar #include <linux/evm.h> 25d46eb369SDmitry Kasatkin #include <crypto/hash.h> 2666dbc325SMimi Zohar #include "evm.h" 2766dbc325SMimi Zohar 2866dbc325SMimi Zohar int evm_initialized; 2966dbc325SMimi Zohar 309b97b6cdSMimi Zohar static char *integrity_status_msg[] = { 319b97b6cdSMimi Zohar "pass", "fail", "no_label", "no_xattrs", "unknown" 329b97b6cdSMimi Zohar }; 3366dbc325SMimi Zohar char *evm_hmac = "hmac(sha1)"; 3415647eb3SDmitry Kasatkin char *evm_hash = "sha1"; 35d3b33679SDmitry Kasatkin int evm_hmac_attrs; 3666dbc325SMimi Zohar 3766dbc325SMimi Zohar char *evm_config_xattrnames[] = { 3866dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX 3966dbc325SMimi Zohar XATTR_NAME_SELINUX, 4066dbc325SMimi Zohar #endif 4166dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK 4266dbc325SMimi Zohar XATTR_NAME_SMACK, 433e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 443e38df56SDmitry Kasatkin XATTR_NAME_SMACKEXEC, 453e38df56SDmitry Kasatkin XATTR_NAME_SMACKTRANSMUTE, 463e38df56SDmitry Kasatkin XATTR_NAME_SMACKMMAP, 473e38df56SDmitry Kasatkin #endif 4866dbc325SMimi Zohar #endif 492fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE 502fe5d6deSMimi Zohar XATTR_NAME_IMA, 512fe5d6deSMimi Zohar #endif 5266dbc325SMimi Zohar XATTR_NAME_CAPS, 5366dbc325SMimi Zohar NULL 5466dbc325SMimi Zohar }; 5566dbc325SMimi Zohar 567102ebcdSMimi Zohar static int evm_fixmode; 577102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str) 587102ebcdSMimi Zohar { 597102ebcdSMimi Zohar if (strncmp(str, "fix", 3) == 0) 607102ebcdSMimi Zohar evm_fixmode = 1; 617102ebcdSMimi Zohar return 0; 627102ebcdSMimi Zohar } 637102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode); 647102ebcdSMimi Zohar 65d3b33679SDmitry Kasatkin static void __init evm_init_config(void) 66d3b33679SDmitry Kasatkin { 67d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID 68d3b33679SDmitry Kasatkin evm_hmac_attrs |= EVM_ATTR_FSUUID; 69d3b33679SDmitry Kasatkin #endif 70d3b33679SDmitry Kasatkin pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs); 71d3b33679SDmitry Kasatkin } 72d3b33679SDmitry Kasatkin 7315647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry) 7415647eb3SDmitry Kasatkin { 7515647eb3SDmitry Kasatkin struct inode *inode = dentry->d_inode; 7615647eb3SDmitry Kasatkin char **xattr; 7715647eb3SDmitry Kasatkin int error; 7815647eb3SDmitry Kasatkin int count = 0; 7915647eb3SDmitry Kasatkin 80627bf81aSAl Viro if (!inode->i_op->getxattr) 8115647eb3SDmitry Kasatkin return -EOPNOTSUPP; 8215647eb3SDmitry Kasatkin 8315647eb3SDmitry Kasatkin for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) { 8415647eb3SDmitry Kasatkin error = inode->i_op->getxattr(dentry, *xattr, NULL, 0); 8515647eb3SDmitry Kasatkin if (error < 0) { 8615647eb3SDmitry Kasatkin if (error == -ENODATA) 8715647eb3SDmitry Kasatkin continue; 8815647eb3SDmitry Kasatkin return error; 8915647eb3SDmitry Kasatkin } 9015647eb3SDmitry Kasatkin count++; 9115647eb3SDmitry Kasatkin } 9215647eb3SDmitry Kasatkin 9315647eb3SDmitry Kasatkin return count; 9415647eb3SDmitry Kasatkin } 9515647eb3SDmitry Kasatkin 9666dbc325SMimi Zohar /* 9766dbc325SMimi Zohar * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 9866dbc325SMimi Zohar * 9966dbc325SMimi Zohar * Compute the HMAC on the dentry's protected set of extended attributes 1007102ebcdSMimi Zohar * and compare it against the stored security.evm xattr. 1017102ebcdSMimi Zohar * 1027102ebcdSMimi Zohar * For performance: 1037102ebcdSMimi Zohar * - use the previoulsy retrieved xattr value and length to calculate the 10466dbc325SMimi Zohar * HMAC.) 1057102ebcdSMimi Zohar * - cache the verification result in the iint, when available. 10666dbc325SMimi Zohar * 10766dbc325SMimi Zohar * Returns integrity status 10866dbc325SMimi Zohar */ 10966dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry, 11066dbc325SMimi Zohar const char *xattr_name, 11166dbc325SMimi Zohar char *xattr_value, 11266dbc325SMimi Zohar size_t xattr_value_len, 11366dbc325SMimi Zohar struct integrity_iint_cache *iint) 11466dbc325SMimi Zohar { 11515647eb3SDmitry Kasatkin struct evm_ima_xattr_data *xattr_data = NULL; 11615647eb3SDmitry Kasatkin struct evm_ima_xattr_data calc; 117566be59aSMimi Zohar enum integrity_status evm_status = INTEGRITY_PASS; 11815647eb3SDmitry Kasatkin int rc, xattr_len; 11966dbc325SMimi Zohar 1207102ebcdSMimi Zohar if (iint && iint->evm_status == INTEGRITY_PASS) 12124e0198eSDmitry Kasatkin return iint->evm_status; 12266dbc325SMimi Zohar 1236d38ca01SDmitry Kasatkin /* if status is not PASS, try to check again - against -ENOMEM */ 1246d38ca01SDmitry Kasatkin 12515647eb3SDmitry Kasatkin /* first need to know the sig type */ 12615647eb3SDmitry Kasatkin rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, 12715647eb3SDmitry Kasatkin GFP_NOFS); 12815647eb3SDmitry Kasatkin if (rc <= 0) { 1291f100979SDmitry Kasatkin evm_status = INTEGRITY_FAIL; 1301f100979SDmitry Kasatkin if (rc == -ENODATA) { 13115647eb3SDmitry Kasatkin rc = evm_find_protected_xattrs(dentry); 13215647eb3SDmitry Kasatkin if (rc > 0) 13315647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOLABEL; 13415647eb3SDmitry Kasatkin else if (rc == 0) 13515647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOXATTRS; /* new file */ 1361f100979SDmitry Kasatkin } else if (rc == -EOPNOTSUPP) { 1371f100979SDmitry Kasatkin evm_status = INTEGRITY_UNKNOWN; 13815647eb3SDmitry Kasatkin } 139566be59aSMimi Zohar goto out; 140566be59aSMimi Zohar } 14166dbc325SMimi Zohar 142b1aaab22SDmitry Kasatkin xattr_len = rc; 14315647eb3SDmitry Kasatkin 14415647eb3SDmitry Kasatkin /* check value type */ 14515647eb3SDmitry Kasatkin switch (xattr_data->type) { 14615647eb3SDmitry Kasatkin case EVM_XATTR_HMAC: 14715647eb3SDmitry Kasatkin rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 14815647eb3SDmitry Kasatkin xattr_value_len, calc.digest); 14915647eb3SDmitry Kasatkin if (rc) 15015647eb3SDmitry Kasatkin break; 15115647eb3SDmitry Kasatkin rc = memcmp(xattr_data->digest, calc.digest, 15215647eb3SDmitry Kasatkin sizeof(calc.digest)); 15315647eb3SDmitry Kasatkin if (rc) 15415647eb3SDmitry Kasatkin rc = -EINVAL; 15515647eb3SDmitry Kasatkin break; 15615647eb3SDmitry Kasatkin case EVM_IMA_XATTR_DIGSIG: 15715647eb3SDmitry Kasatkin rc = evm_calc_hash(dentry, xattr_name, xattr_value, 15815647eb3SDmitry Kasatkin xattr_value_len, calc.digest); 15915647eb3SDmitry Kasatkin if (rc) 16015647eb3SDmitry Kasatkin break; 16115647eb3SDmitry Kasatkin rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, 162b1aaab22SDmitry Kasatkin (const char *)xattr_data, xattr_len, 16315647eb3SDmitry Kasatkin calc.digest, sizeof(calc.digest)); 16415647eb3SDmitry Kasatkin if (!rc) { 16515647eb3SDmitry Kasatkin /* we probably want to replace rsa with hmac here */ 16615647eb3SDmitry Kasatkin evm_update_evmxattr(dentry, xattr_name, xattr_value, 16715647eb3SDmitry Kasatkin xattr_value_len); 16815647eb3SDmitry Kasatkin } 16915647eb3SDmitry Kasatkin break; 17015647eb3SDmitry Kasatkin default: 17115647eb3SDmitry Kasatkin rc = -EINVAL; 17215647eb3SDmitry Kasatkin break; 17315647eb3SDmitry Kasatkin } 17415647eb3SDmitry Kasatkin 17515647eb3SDmitry Kasatkin if (rc) 17615647eb3SDmitry Kasatkin evm_status = (rc == -ENODATA) ? 17715647eb3SDmitry Kasatkin INTEGRITY_NOXATTRS : INTEGRITY_FAIL; 1787102ebcdSMimi Zohar out: 1797102ebcdSMimi Zohar if (iint) 1807102ebcdSMimi Zohar iint->evm_status = evm_status; 18115647eb3SDmitry Kasatkin kfree(xattr_data); 1827102ebcdSMimi Zohar return evm_status; 18366dbc325SMimi Zohar } 18466dbc325SMimi Zohar 18566dbc325SMimi Zohar static int evm_protected_xattr(const char *req_xattr_name) 18666dbc325SMimi Zohar { 18766dbc325SMimi Zohar char **xattrname; 18866dbc325SMimi Zohar int namelen; 18966dbc325SMimi Zohar int found = 0; 19066dbc325SMimi Zohar 19166dbc325SMimi Zohar namelen = strlen(req_xattr_name); 19266dbc325SMimi Zohar for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { 19366dbc325SMimi Zohar if ((strlen(*xattrname) == namelen) 19466dbc325SMimi Zohar && (strncmp(req_xattr_name, *xattrname, namelen) == 0)) { 19566dbc325SMimi Zohar found = 1; 19666dbc325SMimi Zohar break; 19766dbc325SMimi Zohar } 198cb723180SMimi Zohar if (strncmp(req_xattr_name, 199cb723180SMimi Zohar *xattrname + XATTR_SECURITY_PREFIX_LEN, 200cb723180SMimi Zohar strlen(req_xattr_name)) == 0) { 201cb723180SMimi Zohar found = 1; 202cb723180SMimi Zohar break; 203cb723180SMimi Zohar } 20466dbc325SMimi Zohar } 20566dbc325SMimi Zohar return found; 20666dbc325SMimi Zohar } 20766dbc325SMimi Zohar 20866dbc325SMimi Zohar /** 20966dbc325SMimi Zohar * evm_verifyxattr - verify the integrity of the requested xattr 21066dbc325SMimi Zohar * @dentry: object of the verify xattr 21166dbc325SMimi Zohar * @xattr_name: requested xattr 21266dbc325SMimi Zohar * @xattr_value: requested xattr value 21366dbc325SMimi Zohar * @xattr_value_len: requested xattr value length 21466dbc325SMimi Zohar * 21566dbc325SMimi Zohar * Calculate the HMAC for the given dentry and verify it against the stored 21666dbc325SMimi Zohar * security.evm xattr. For performance, use the xattr value and length 21766dbc325SMimi Zohar * previously retrieved to calculate the HMAC. 21866dbc325SMimi Zohar * 21966dbc325SMimi Zohar * Returns the xattr integrity status. 22066dbc325SMimi Zohar * 22166dbc325SMimi Zohar * This function requires the caller to lock the inode's i_mutex before it 22266dbc325SMimi Zohar * is executed. 22366dbc325SMimi Zohar */ 22466dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry, 22566dbc325SMimi Zohar const char *xattr_name, 2262960e6cbSDmitry Kasatkin void *xattr_value, size_t xattr_value_len, 2272960e6cbSDmitry Kasatkin struct integrity_iint_cache *iint) 22866dbc325SMimi Zohar { 22966dbc325SMimi Zohar if (!evm_initialized || !evm_protected_xattr(xattr_name)) 23066dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 23166dbc325SMimi Zohar 2322960e6cbSDmitry Kasatkin if (!iint) { 2332960e6cbSDmitry Kasatkin iint = integrity_iint_find(dentry->d_inode); 23466dbc325SMimi Zohar if (!iint) 23566dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 2362960e6cbSDmitry Kasatkin } 2372960e6cbSDmitry Kasatkin return evm_verify_hmac(dentry, xattr_name, xattr_value, 23866dbc325SMimi Zohar xattr_value_len, iint); 23966dbc325SMimi Zohar } 24066dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr); 24166dbc325SMimi Zohar 24266dbc325SMimi Zohar /* 2437102ebcdSMimi Zohar * evm_verify_current_integrity - verify the dentry's metadata integrity 2447102ebcdSMimi Zohar * @dentry: pointer to the affected dentry 2457102ebcdSMimi Zohar * 2467102ebcdSMimi Zohar * Verify and return the dentry's metadata integrity. The exceptions are 2477102ebcdSMimi Zohar * before EVM is initialized or in 'fix' mode. 2487102ebcdSMimi Zohar */ 2497102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) 2507102ebcdSMimi Zohar { 2517102ebcdSMimi Zohar struct inode *inode = dentry->d_inode; 2527102ebcdSMimi Zohar 2537102ebcdSMimi Zohar if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode) 2547102ebcdSMimi Zohar return 0; 2557102ebcdSMimi Zohar return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 2567102ebcdSMimi Zohar } 2577102ebcdSMimi Zohar 258a924ce0bSMimi Zohar /* 259a924ce0bSMimi Zohar * evm_protect_xattr - protect the EVM extended attribute 260a924ce0bSMimi Zohar * 261bf6d0f5dSMimi Zohar * Prevent security.evm from being modified or removed without the 262bf6d0f5dSMimi Zohar * necessary permissions or when the existing value is invalid. 263bf6d0f5dSMimi Zohar * 264bf6d0f5dSMimi Zohar * The posix xattr acls are 'system' prefixed, which normally would not 265bf6d0f5dSMimi Zohar * affect security.evm. An interesting side affect of writing posix xattr 266bf6d0f5dSMimi Zohar * acls is their modifying of the i_mode, which is included in security.evm. 267bf6d0f5dSMimi Zohar * For posix xattr acls only, permit security.evm, even if it currently 268bf6d0f5dSMimi Zohar * doesn't exist, to be updated. 269a924ce0bSMimi Zohar */ 270a924ce0bSMimi Zohar static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, 271a924ce0bSMimi Zohar const void *xattr_value, size_t xattr_value_len) 272a924ce0bSMimi Zohar { 273a924ce0bSMimi Zohar enum integrity_status evm_status; 274a924ce0bSMimi Zohar 275a924ce0bSMimi Zohar if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 276a924ce0bSMimi Zohar if (!capable(CAP_SYS_ADMIN)) 277a924ce0bSMimi Zohar return -EPERM; 278bf6d0f5dSMimi Zohar } else if (!evm_protected_xattr(xattr_name)) { 279bf6d0f5dSMimi Zohar if (!posix_xattr_acl(xattr_name)) 280a924ce0bSMimi Zohar return 0; 281bf6d0f5dSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 282bf6d0f5dSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 283566be59aSMimi Zohar (evm_status == INTEGRITY_NOXATTRS)) 284bf6d0f5dSMimi Zohar return 0; 2859b97b6cdSMimi Zohar goto out; 286bf6d0f5dSMimi Zohar } 287a924ce0bSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 2883dcbad52SDmitry Kasatkin if (evm_status == INTEGRITY_NOXATTRS) { 2893dcbad52SDmitry Kasatkin struct integrity_iint_cache *iint; 2903dcbad52SDmitry Kasatkin 2913dcbad52SDmitry Kasatkin iint = integrity_iint_find(dentry->d_inode); 2923dcbad52SDmitry Kasatkin if (iint && (iint->flags & IMA_NEW_FILE)) 2933dcbad52SDmitry Kasatkin return 0; 2943dcbad52SDmitry Kasatkin } 2959b97b6cdSMimi Zohar out: 2969b97b6cdSMimi Zohar if (evm_status != INTEGRITY_PASS) 2979b97b6cdSMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, 2989b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 2999b97b6cdSMimi Zohar integrity_status_msg[evm_status], 3009b97b6cdSMimi Zohar -EPERM, 0); 301a924ce0bSMimi Zohar return evm_status == INTEGRITY_PASS ? 0 : -EPERM; 302a924ce0bSMimi Zohar } 303a924ce0bSMimi Zohar 30466dbc325SMimi Zohar /** 30566dbc325SMimi Zohar * evm_inode_setxattr - protect the EVM extended attribute 30666dbc325SMimi Zohar * @dentry: pointer to the affected dentry 30766dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 30866dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 30966dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 31066dbc325SMimi Zohar * 3112fb1c9a4SMimi Zohar * Before allowing the 'security.evm' protected xattr to be updated, 3122fb1c9a4SMimi Zohar * verify the existing value is valid. As only the kernel should have 3132fb1c9a4SMimi Zohar * access to the EVM encrypted key needed to calculate the HMAC, prevent 3142fb1c9a4SMimi Zohar * userspace from writing HMAC value. Writing 'security.evm' requires 3152fb1c9a4SMimi Zohar * requires CAP_SYS_ADMIN privileges. 31666dbc325SMimi Zohar */ 31766dbc325SMimi Zohar int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, 31866dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 31966dbc325SMimi Zohar { 3202fb1c9a4SMimi Zohar const struct evm_ima_xattr_data *xattr_data = xattr_value; 3212fb1c9a4SMimi Zohar 3222fb1c9a4SMimi Zohar if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0) 3232fb1c9a4SMimi Zohar && (xattr_data->type == EVM_XATTR_HMAC)) 3242fb1c9a4SMimi Zohar return -EPERM; 325a924ce0bSMimi Zohar return evm_protect_xattr(dentry, xattr_name, xattr_value, 32666dbc325SMimi Zohar xattr_value_len); 32766dbc325SMimi Zohar } 32866dbc325SMimi Zohar 32966dbc325SMimi Zohar /** 33066dbc325SMimi Zohar * evm_inode_removexattr - protect the EVM extended attribute 33166dbc325SMimi Zohar * @dentry: pointer to the affected dentry 33266dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 33366dbc325SMimi Zohar * 3347102ebcdSMimi Zohar * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that 3357102ebcdSMimi Zohar * the current value is valid. 33666dbc325SMimi Zohar */ 33766dbc325SMimi Zohar int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name) 33866dbc325SMimi Zohar { 339a924ce0bSMimi Zohar return evm_protect_xattr(dentry, xattr_name, NULL, 0); 34066dbc325SMimi Zohar } 34166dbc325SMimi Zohar 34266dbc325SMimi Zohar /** 34366dbc325SMimi Zohar * evm_inode_post_setxattr - update 'security.evm' to reflect the changes 34466dbc325SMimi Zohar * @dentry: pointer to the affected dentry 34566dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 34666dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 34766dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 34866dbc325SMimi Zohar * 34966dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect the change. 35066dbc325SMimi Zohar * 35166dbc325SMimi Zohar * No need to take the i_mutex lock here, as this function is called from 35266dbc325SMimi Zohar * __vfs_setxattr_noperm(). The caller of which has taken the inode's 35366dbc325SMimi Zohar * i_mutex lock. 35466dbc325SMimi Zohar */ 35566dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, 35666dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 35766dbc325SMimi Zohar { 358bf6d0f5dSMimi Zohar if (!evm_initialized || (!evm_protected_xattr(xattr_name) 359bf6d0f5dSMimi Zohar && !posix_xattr_acl(xattr_name))) 36066dbc325SMimi Zohar return; 36166dbc325SMimi Zohar 36266dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); 36366dbc325SMimi Zohar } 36466dbc325SMimi Zohar 36566dbc325SMimi Zohar /** 36666dbc325SMimi Zohar * evm_inode_post_removexattr - update 'security.evm' after removing the xattr 36766dbc325SMimi Zohar * @dentry: pointer to the affected dentry 36866dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 36966dbc325SMimi Zohar * 37066dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. 37166dbc325SMimi Zohar */ 37266dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) 37366dbc325SMimi Zohar { 37466dbc325SMimi Zohar struct inode *inode = dentry->d_inode; 37566dbc325SMimi Zohar 37666dbc325SMimi Zohar if (!evm_initialized || !evm_protected_xattr(xattr_name)) 37766dbc325SMimi Zohar return; 37866dbc325SMimi Zohar 37966dbc325SMimi Zohar mutex_lock(&inode->i_mutex); 38066dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, NULL, 0); 38166dbc325SMimi Zohar mutex_unlock(&inode->i_mutex); 38266dbc325SMimi Zohar } 38366dbc325SMimi Zohar 38466dbc325SMimi Zohar /** 385817b54aaSMimi Zohar * evm_inode_setattr - prevent updating an invalid EVM extended attribute 386817b54aaSMimi Zohar * @dentry: pointer to the affected dentry 387817b54aaSMimi Zohar */ 388817b54aaSMimi Zohar int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) 389817b54aaSMimi Zohar { 390817b54aaSMimi Zohar unsigned int ia_valid = attr->ia_valid; 391817b54aaSMimi Zohar enum integrity_status evm_status; 392817b54aaSMimi Zohar 393a924ce0bSMimi Zohar if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))) 394817b54aaSMimi Zohar return 0; 395817b54aaSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 396566be59aSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 397566be59aSMimi Zohar (evm_status == INTEGRITY_NOXATTRS)) 398566be59aSMimi Zohar return 0; 3999b97b6cdSMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, 4009b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 4019b97b6cdSMimi Zohar integrity_status_msg[evm_status], -EPERM, 0); 402566be59aSMimi Zohar return -EPERM; 403817b54aaSMimi Zohar } 404817b54aaSMimi Zohar 405817b54aaSMimi Zohar /** 40666dbc325SMimi Zohar * evm_inode_post_setattr - update 'security.evm' after modifying metadata 40766dbc325SMimi Zohar * @dentry: pointer to the affected dentry 40866dbc325SMimi Zohar * @ia_valid: for the UID and GID status 40966dbc325SMimi Zohar * 41066dbc325SMimi Zohar * For now, update the HMAC stored in 'security.evm' to reflect UID/GID 41166dbc325SMimi Zohar * changes. 41266dbc325SMimi Zohar * 41366dbc325SMimi Zohar * This function is called from notify_change(), which expects the caller 41466dbc325SMimi Zohar * to lock the inode's i_mutex. 41566dbc325SMimi Zohar */ 41666dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) 41766dbc325SMimi Zohar { 41866dbc325SMimi Zohar if (!evm_initialized) 41966dbc325SMimi Zohar return; 42066dbc325SMimi Zohar 42166dbc325SMimi Zohar if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) 42266dbc325SMimi Zohar evm_update_evmxattr(dentry, NULL, NULL, 0); 42366dbc325SMimi Zohar } 42466dbc325SMimi Zohar 425cb723180SMimi Zohar /* 426cb723180SMimi Zohar * evm_inode_init_security - initializes security.evm 427cb723180SMimi Zohar */ 428cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode, 429cb723180SMimi Zohar const struct xattr *lsm_xattr, 430cb723180SMimi Zohar struct xattr *evm_xattr) 431cb723180SMimi Zohar { 432cb723180SMimi Zohar struct evm_ima_xattr_data *xattr_data; 433cb723180SMimi Zohar int rc; 434cb723180SMimi Zohar 435cb723180SMimi Zohar if (!evm_initialized || !evm_protected_xattr(lsm_xattr->name)) 4365a4730baSMimi Zohar return 0; 437cb723180SMimi Zohar 438cb723180SMimi Zohar xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); 439cb723180SMimi Zohar if (!xattr_data) 440cb723180SMimi Zohar return -ENOMEM; 441cb723180SMimi Zohar 442cb723180SMimi Zohar xattr_data->type = EVM_XATTR_HMAC; 443cb723180SMimi Zohar rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); 444cb723180SMimi Zohar if (rc < 0) 445cb723180SMimi Zohar goto out; 446cb723180SMimi Zohar 447cb723180SMimi Zohar evm_xattr->value = xattr_data; 448cb723180SMimi Zohar evm_xattr->value_len = sizeof(*xattr_data); 4499548906bSTetsuo Handa evm_xattr->name = XATTR_EVM_SUFFIX; 450cb723180SMimi Zohar return 0; 451cb723180SMimi Zohar out: 452cb723180SMimi Zohar kfree(xattr_data); 453cb723180SMimi Zohar return rc; 454cb723180SMimi Zohar } 455cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security); 456cb723180SMimi Zohar 45766dbc325SMimi Zohar static int __init init_evm(void) 45866dbc325SMimi Zohar { 45966dbc325SMimi Zohar int error; 46066dbc325SMimi Zohar 461d3b33679SDmitry Kasatkin evm_init_config(); 462d3b33679SDmitry Kasatkin 46366dbc325SMimi Zohar error = evm_init_secfs(); 46466dbc325SMimi Zohar if (error < 0) { 46520ee451fSJoe Perches pr_info("Error registering secfs\n"); 46666dbc325SMimi Zohar goto err; 46766dbc325SMimi Zohar } 46815647eb3SDmitry Kasatkin 46915647eb3SDmitry Kasatkin return 0; 47066dbc325SMimi Zohar err: 47166dbc325SMimi Zohar return error; 47266dbc325SMimi Zohar } 47366dbc325SMimi Zohar 47466dbc325SMimi Zohar /* 47566dbc325SMimi Zohar * evm_display_config - list the EVM protected security extended attributes 47666dbc325SMimi Zohar */ 47766dbc325SMimi Zohar static int __init evm_display_config(void) 47866dbc325SMimi Zohar { 47966dbc325SMimi Zohar char **xattrname; 48066dbc325SMimi Zohar 48166dbc325SMimi Zohar for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) 48220ee451fSJoe Perches pr_info("%s\n", *xattrname); 48366dbc325SMimi Zohar return 0; 48466dbc325SMimi Zohar } 48566dbc325SMimi Zohar 48666dbc325SMimi Zohar pure_initcall(evm_display_config); 48766dbc325SMimi Zohar late_initcall(init_evm); 48866dbc325SMimi Zohar 48966dbc325SMimi Zohar MODULE_DESCRIPTION("Extended Verification Module"); 49066dbc325SMimi Zohar MODULE_LICENSE("GPL"); 491