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