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