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,
11e61b135fSChristian Brauner  *	evm_inode_removexattr, evm_verifyxattr, and evm_inode_set_acl.
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>
246db7d1deSRoberto Sassu #include <linux/lsm_hooks.h>
2550d34394SIngo Molnar 
26d46eb369SDmitry Kasatkin #include <crypto/hash.h>
275feeb611SMatthew Garrett #include <crypto/hash_info.h>
28613317bdSRyan Ware #include <crypto/algapi.h>
2966dbc325SMimi Zohar #include "evm.h"
3066dbc325SMimi Zohar 
3166dbc325SMimi Zohar int evm_initialized;
3266dbc325SMimi Zohar 
3317d7b0afSHernán Gonzalez static const char * const integrity_status_msg[] = {
34cdef685bSRoberto Sassu 	"pass", "pass_immutable", "fail", "fail_immutable", "no_label",
35cdef685bSRoberto Sassu 	"no_xattrs", "unknown"
369b97b6cdSMimi Zohar };
37d3b33679SDmitry Kasatkin int evm_hmac_attrs;
3866dbc325SMimi Zohar 
39fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = {
40c808a6ecSXiu Jianfeng 	{
41c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_SELINUX,
42c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_SECURITY_SELINUX)
438c7a703eSRoberto Sassu 	},
44c808a6ecSXiu Jianfeng 	{
45c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_SMACK,
46c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_SECURITY_SMACK)
478c7a703eSRoberto Sassu 	},
48c808a6ecSXiu Jianfeng 	{
49c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_SMACKEXEC,
50c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_EVM_EXTRA_SMACK_XATTRS)
518c7a703eSRoberto Sassu 	},
52c808a6ecSXiu Jianfeng 	{
53c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_SMACKTRANSMUTE,
54c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_EVM_EXTRA_SMACK_XATTRS)
558c7a703eSRoberto Sassu 	},
56c808a6ecSXiu Jianfeng 	{
57c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_SMACKMMAP,
58c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_EVM_EXTRA_SMACK_XATTRS)
598c7a703eSRoberto Sassu 	},
60c808a6ecSXiu Jianfeng 	{
61c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_APPARMOR,
62c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_SECURITY_APPARMOR)
638c7a703eSRoberto Sassu 	},
64c808a6ecSXiu Jianfeng 	{
65c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_IMA,
66c808a6ecSXiu Jianfeng 	 .enabled = IS_ENABLED(CONFIG_IMA_APPRAISE)
678c7a703eSRoberto Sassu 	},
68c808a6ecSXiu Jianfeng 	{
69c808a6ecSXiu Jianfeng 	 .name = XATTR_NAME_CAPS,
708c7a703eSRoberto Sassu 	 .enabled = true
718c7a703eSRoberto Sassu 	},
7266dbc325SMimi Zohar };
7366dbc325SMimi Zohar 
7421af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames);
7521af7663SMatthew Garrett 
7632ba540fSAustin Kim static int evm_fixmode __ro_after_init;
evm_set_fixmode(char * str)777102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str)
787102ebcdSMimi Zohar {
797102ebcdSMimi Zohar 	if (strncmp(str, "fix", 3) == 0)
807102ebcdSMimi Zohar 		evm_fixmode = 1;
817fe2bb7eSBruno Meneguele 	else
827fe2bb7eSBruno Meneguele 		pr_err("invalid \"%s\" mode", str);
837fe2bb7eSBruno Meneguele 
84f2544f5eSRandy Dunlap 	return 1;
857102ebcdSMimi Zohar }
867102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode);
877102ebcdSMimi Zohar 
evm_init_config(void)88d3b33679SDmitry Kasatkin static void __init evm_init_config(void)
89d3b33679SDmitry Kasatkin {
9021af7663SMatthew Garrett 	int i, xattrs;
9121af7663SMatthew Garrett 
9221af7663SMatthew Garrett 	xattrs = ARRAY_SIZE(evm_config_default_xattrnames);
9321af7663SMatthew Garrett 
9421af7663SMatthew Garrett 	pr_info("Initialising EVM extended attributes:\n");
9521af7663SMatthew Garrett 	for (i = 0; i < xattrs; i++) {
968c7a703eSRoberto Sassu 		pr_info("%s%s\n", evm_config_default_xattrnames[i].name,
978c7a703eSRoberto Sassu 			!evm_config_default_xattrnames[i].enabled ?
988c7a703eSRoberto Sassu 			" (disabled)" : "");
9921af7663SMatthew Garrett 		list_add_tail(&evm_config_default_xattrnames[i].list,
10021af7663SMatthew Garrett 			      &evm_config_xattrnames);
10121af7663SMatthew Garrett 	}
10221af7663SMatthew Garrett 
103d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID
104d3b33679SDmitry Kasatkin 	evm_hmac_attrs |= EVM_ATTR_FSUUID;
105d3b33679SDmitry Kasatkin #endif
106d3b33679SDmitry Kasatkin 	pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs);
107d3b33679SDmitry Kasatkin }
108d3b33679SDmitry Kasatkin 
evm_key_loaded(void)109ae1ba167SMatthew Garrett static bool evm_key_loaded(void)
110ae1ba167SMatthew Garrett {
111ae1ba167SMatthew Garrett 	return (bool)(evm_initialized & EVM_KEY_MASK);
112ae1ba167SMatthew Garrett }
113ae1ba167SMatthew Garrett 
1144a804b8aSRoberto Sassu /*
1154a804b8aSRoberto Sassu  * This function determines whether or not it is safe to ignore verification
1164a804b8aSRoberto Sassu  * errors, based on the ability of EVM to calculate HMACs. If the HMAC key
1174a804b8aSRoberto Sassu  * is not loaded, and it cannot be loaded in the future due to the
1184a804b8aSRoberto Sassu  * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the
1194a804b8aSRoberto Sassu  * attrs/xattrs being found invalid will not make them valid.
1204a804b8aSRoberto Sassu  */
evm_hmac_disabled(void)1214a804b8aSRoberto Sassu static bool evm_hmac_disabled(void)
1224a804b8aSRoberto Sassu {
1234a804b8aSRoberto Sassu 	if (evm_initialized & EVM_INIT_HMAC)
1244a804b8aSRoberto Sassu 		return false;
1254a804b8aSRoberto Sassu 
1264a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_SETUP_COMPLETE))
1274a804b8aSRoberto Sassu 		return false;
1284a804b8aSRoberto Sassu 
1294a804b8aSRoberto Sassu 	return true;
1304a804b8aSRoberto Sassu }
1314a804b8aSRoberto Sassu 
evm_find_protected_xattrs(struct dentry * dentry)13215647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry)
13315647eb3SDmitry Kasatkin {
134c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
13521af7663SMatthew Garrett 	struct xattr_list *xattr;
13615647eb3SDmitry Kasatkin 	int error;
13715647eb3SDmitry Kasatkin 	int count = 0;
13815647eb3SDmitry Kasatkin 
1395d6c3191SAndreas Gruenbacher 	if (!(inode->i_opflags & IOP_XATTR))
14015647eb3SDmitry Kasatkin 		return -EOPNOTSUPP;
14115647eb3SDmitry Kasatkin 
142770f6058SMadhuparna Bhowmik 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
14321af7663SMatthew Garrett 		error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
14415647eb3SDmitry Kasatkin 		if (error < 0) {
14515647eb3SDmitry Kasatkin 			if (error == -ENODATA)
14615647eb3SDmitry Kasatkin 				continue;
14715647eb3SDmitry Kasatkin 			return error;
14815647eb3SDmitry Kasatkin 		}
14915647eb3SDmitry Kasatkin 		count++;
15015647eb3SDmitry Kasatkin 	}
15115647eb3SDmitry Kasatkin 
15215647eb3SDmitry Kasatkin 	return count;
15315647eb3SDmitry Kasatkin }
15415647eb3SDmitry Kasatkin 
15566dbc325SMimi Zohar /*
15666dbc325SMimi Zohar  * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
15766dbc325SMimi Zohar  *
15866dbc325SMimi Zohar  * Compute the HMAC on the dentry's protected set of extended attributes
1597102ebcdSMimi Zohar  * and compare it against the stored security.evm xattr.
1607102ebcdSMimi Zohar  *
1617102ebcdSMimi Zohar  * For performance:
1627102ebcdSMimi Zohar  * - use the previoulsy retrieved xattr value and length to calculate the
16366dbc325SMimi Zohar  *   HMAC.)
1647102ebcdSMimi Zohar  * - cache the verification result in the iint, when available.
16566dbc325SMimi Zohar  *
16666dbc325SMimi Zohar  * Returns integrity status
16766dbc325SMimi Zohar  */
evm_verify_hmac(struct dentry * dentry,const char * xattr_name,char * xattr_value,size_t xattr_value_len,struct integrity_iint_cache * iint)16866dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry,
16966dbc325SMimi Zohar 					     const char *xattr_name,
17066dbc325SMimi Zohar 					     char *xattr_value,
17166dbc325SMimi Zohar 					     size_t xattr_value_len,
17266dbc325SMimi Zohar 					     struct integrity_iint_cache *iint)
17366dbc325SMimi Zohar {
17415647eb3SDmitry Kasatkin 	struct evm_ima_xattr_data *xattr_data = NULL;
1755feeb611SMatthew Garrett 	struct signature_v2_hdr *hdr;
176566be59aSMimi Zohar 	enum integrity_status evm_status = INTEGRITY_PASS;
1775feeb611SMatthew Garrett 	struct evm_digest digest;
17870946c4aSSascha Hauer 	struct inode *inode;
179cdef685bSRoberto Sassu 	int rc, xattr_len, evm_immutable = 0;
18066dbc325SMimi Zohar 
18150b97748SMatthew Garrett 	if (iint && (iint->evm_status == INTEGRITY_PASS ||
18250b97748SMatthew Garrett 		     iint->evm_status == INTEGRITY_PASS_IMMUTABLE))
18324e0198eSDmitry Kasatkin 		return iint->evm_status;
18466dbc325SMimi Zohar 
1856d38ca01SDmitry Kasatkin 	/* if status is not PASS, try to check again - against -ENOMEM */
1866d38ca01SDmitry Kasatkin 
18715647eb3SDmitry Kasatkin 	/* first need to know the sig type */
1884609e1f1SChristian Brauner 	rc = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, XATTR_NAME_EVM,
189c7c7a1a1STycho Andersen 				(char **)&xattr_data, 0, GFP_NOFS);
19015647eb3SDmitry Kasatkin 	if (rc <= 0) {
1911f100979SDmitry Kasatkin 		evm_status = INTEGRITY_FAIL;
1921f100979SDmitry Kasatkin 		if (rc == -ENODATA) {
19315647eb3SDmitry Kasatkin 			rc = evm_find_protected_xattrs(dentry);
19415647eb3SDmitry Kasatkin 			if (rc > 0)
19515647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOLABEL;
19615647eb3SDmitry Kasatkin 			else if (rc == 0)
19715647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOXATTRS; /* new file */
1981f100979SDmitry Kasatkin 		} else if (rc == -EOPNOTSUPP) {
1991f100979SDmitry Kasatkin 			evm_status = INTEGRITY_UNKNOWN;
20015647eb3SDmitry Kasatkin 		}
201566be59aSMimi Zohar 		goto out;
202566be59aSMimi Zohar 	}
20366dbc325SMimi Zohar 
204b1aaab22SDmitry Kasatkin 	xattr_len = rc;
20515647eb3SDmitry Kasatkin 
20615647eb3SDmitry Kasatkin 	/* check value type */
20715647eb3SDmitry Kasatkin 	switch (xattr_data->type) {
20815647eb3SDmitry Kasatkin 	case EVM_XATTR_HMAC:
209650b29dbSThiago Jung Bauermann 		if (xattr_len != sizeof(struct evm_xattr)) {
210b4bfec7fSSeth Forshee 			evm_status = INTEGRITY_FAIL;
211b4bfec7fSSeth Forshee 			goto out;
212b4bfec7fSSeth Forshee 		}
2135feeb611SMatthew Garrett 
2145feeb611SMatthew Garrett 		digest.hdr.algo = HASH_ALGO_SHA1;
21515647eb3SDmitry Kasatkin 		rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
2165feeb611SMatthew Garrett 				   xattr_value_len, &digest);
21715647eb3SDmitry Kasatkin 		if (rc)
21815647eb3SDmitry Kasatkin 			break;
219650b29dbSThiago Jung Bauermann 		rc = crypto_memneq(xattr_data->data, digest.digest,
2205feeb611SMatthew Garrett 				   SHA1_DIGEST_SIZE);
22115647eb3SDmitry Kasatkin 		if (rc)
22215647eb3SDmitry Kasatkin 			rc = -EINVAL;
22315647eb3SDmitry Kasatkin 		break;
22450b97748SMatthew Garrett 	case EVM_XATTR_PORTABLE_DIGSIG:
225cdef685bSRoberto Sassu 		evm_immutable = 1;
226cdef685bSRoberto Sassu 		fallthrough;
227cdef685bSRoberto Sassu 	case EVM_IMA_XATTR_DIGSIG:
228455b6c91SRoberto Sassu 		/* accept xattr with non-empty signature field */
229455b6c91SRoberto Sassu 		if (xattr_len <= sizeof(struct signature_v2_hdr)) {
230455b6c91SRoberto Sassu 			evm_status = INTEGRITY_FAIL;
231455b6c91SRoberto Sassu 			goto out;
232455b6c91SRoberto Sassu 		}
233455b6c91SRoberto Sassu 
2345feeb611SMatthew Garrett 		hdr = (struct signature_v2_hdr *)xattr_data;
2355feeb611SMatthew Garrett 		digest.hdr.algo = hdr->hash_algo;
23615647eb3SDmitry Kasatkin 		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
2375feeb611SMatthew Garrett 				   xattr_value_len, xattr_data->type, &digest);
23815647eb3SDmitry Kasatkin 		if (rc)
23915647eb3SDmitry Kasatkin 			break;
24015647eb3SDmitry Kasatkin 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
241b1aaab22SDmitry Kasatkin 					(const char *)xattr_data, xattr_len,
2425feeb611SMatthew Garrett 					digest.digest, digest.hdr.length);
24315647eb3SDmitry Kasatkin 		if (!rc) {
24470946c4aSSascha Hauer 			inode = d_backing_inode(dentry);
24570946c4aSSascha Hauer 
24650b97748SMatthew Garrett 			if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
24750b97748SMatthew Garrett 				if (iint)
24850b97748SMatthew Garrett 					iint->flags |= EVM_IMMUTABLE_DIGSIG;
24950b97748SMatthew Garrett 				evm_status = INTEGRITY_PASS_IMMUTABLE;
25070946c4aSSascha Hauer 			} else if (!IS_RDONLY(inode) &&
25170946c4aSSascha Hauer 				   !(inode->i_sb->s_readonly_remount) &&
25270946c4aSSascha Hauer 				   !IS_IMMUTABLE(inode)) {
253c2baec7fSDmitry Kasatkin 				evm_update_evmxattr(dentry, xattr_name,
254c2baec7fSDmitry Kasatkin 						    xattr_value,
25515647eb3SDmitry Kasatkin 						    xattr_value_len);
25615647eb3SDmitry Kasatkin 			}
25750b97748SMatthew Garrett 		}
25815647eb3SDmitry Kasatkin 		break;
25915647eb3SDmitry Kasatkin 	default:
26015647eb3SDmitry Kasatkin 		rc = -EINVAL;
26115647eb3SDmitry Kasatkin 		break;
26215647eb3SDmitry Kasatkin 	}
26315647eb3SDmitry Kasatkin 
264cdef685bSRoberto Sassu 	if (rc) {
265cdef685bSRoberto Sassu 		if (rc == -ENODATA)
266cdef685bSRoberto Sassu 			evm_status = INTEGRITY_NOXATTRS;
267cdef685bSRoberto Sassu 		else if (evm_immutable)
268cdef685bSRoberto Sassu 			evm_status = INTEGRITY_FAIL_IMMUTABLE;
269cdef685bSRoberto Sassu 		else
270cdef685bSRoberto Sassu 			evm_status = INTEGRITY_FAIL;
271cdef685bSRoberto Sassu 	}
27287ac3d00SMimi Zohar 	pr_debug("digest: (%d) [%*phN]\n", digest.hdr.length, digest.hdr.length,
27387ac3d00SMimi Zohar 		  digest.digest);
2747102ebcdSMimi Zohar out:
2757102ebcdSMimi Zohar 	if (iint)
2767102ebcdSMimi Zohar 		iint->evm_status = evm_status;
27715647eb3SDmitry Kasatkin 	kfree(xattr_data);
2787102ebcdSMimi Zohar 	return evm_status;
27966dbc325SMimi Zohar }
28066dbc325SMimi Zohar 
evm_protected_xattr_common(const char * req_xattr_name,bool all_xattrs)2818c7a703eSRoberto Sassu static int evm_protected_xattr_common(const char *req_xattr_name,
2828c7a703eSRoberto Sassu 				      bool all_xattrs)
28366dbc325SMimi Zohar {
28466dbc325SMimi Zohar 	int namelen;
28566dbc325SMimi Zohar 	int found = 0;
28621af7663SMatthew Garrett 	struct xattr_list *xattr;
28766dbc325SMimi Zohar 
28866dbc325SMimi Zohar 	namelen = strlen(req_xattr_name);
289770f6058SMadhuparna Bhowmik 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
2908c7a703eSRoberto Sassu 		if (!all_xattrs && !xattr->enabled)
2918c7a703eSRoberto Sassu 			continue;
2928c7a703eSRoberto Sassu 
29321af7663SMatthew Garrett 		if ((strlen(xattr->name) == namelen)
29421af7663SMatthew Garrett 		    && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
29566dbc325SMimi Zohar 			found = 1;
29666dbc325SMimi Zohar 			break;
29766dbc325SMimi Zohar 		}
298cb723180SMimi Zohar 		if (strncmp(req_xattr_name,
29921af7663SMatthew Garrett 			    xattr->name + XATTR_SECURITY_PREFIX_LEN,
300cb723180SMimi Zohar 			    strlen(req_xattr_name)) == 0) {
301cb723180SMimi Zohar 			found = 1;
302cb723180SMimi Zohar 			break;
303cb723180SMimi Zohar 		}
30466dbc325SMimi Zohar 	}
30521af7663SMatthew Garrett 
30666dbc325SMimi Zohar 	return found;
30766dbc325SMimi Zohar }
30866dbc325SMimi Zohar 
evm_protected_xattr(const char * req_xattr_name)309*c31288e5SRoberto Sassu int evm_protected_xattr(const char *req_xattr_name)
3108c7a703eSRoberto Sassu {
3118c7a703eSRoberto Sassu 	return evm_protected_xattr_common(req_xattr_name, false);
3128c7a703eSRoberto Sassu }
3138c7a703eSRoberto Sassu 
evm_protected_xattr_if_enabled(const char * req_xattr_name)3148c7a703eSRoberto Sassu int evm_protected_xattr_if_enabled(const char *req_xattr_name)
3158c7a703eSRoberto Sassu {
3168c7a703eSRoberto Sassu 	return evm_protected_xattr_common(req_xattr_name, true);
3178c7a703eSRoberto Sassu }
3188c7a703eSRoberto Sassu 
31966dbc325SMimi Zohar /**
3208314b673SRoberto Sassu  * evm_read_protected_xattrs - read EVM protected xattr names, lengths, values
3218314b673SRoberto Sassu  * @dentry: dentry of the read xattrs
3228314b673SRoberto Sassu  * @buffer: buffer xattr names, lengths or values are copied to
3238314b673SRoberto Sassu  * @buffer_size: size of buffer
3248314b673SRoberto Sassu  * @type: n: names, l: lengths, v: values
3258314b673SRoberto Sassu  * @canonical_fmt: data format (true: little endian, false: native format)
3268314b673SRoberto Sassu  *
3278314b673SRoberto Sassu  * Read protected xattr names (separated by |), lengths (u32) or values for a
3288314b673SRoberto Sassu  * given dentry and return the total size of copied data. If buffer is NULL,
3298314b673SRoberto Sassu  * just return the total size.
3308314b673SRoberto Sassu  *
3318314b673SRoberto Sassu  * Returns the total size on success, a negative value on error.
3328314b673SRoberto Sassu  */
evm_read_protected_xattrs(struct dentry * dentry,u8 * buffer,int buffer_size,char type,bool canonical_fmt)3338314b673SRoberto Sassu int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
3348314b673SRoberto Sassu 			      int buffer_size, char type, bool canonical_fmt)
3358314b673SRoberto Sassu {
3368314b673SRoberto Sassu 	struct xattr_list *xattr;
3378314b673SRoberto Sassu 	int rc, size, total_size = 0;
3388314b673SRoberto Sassu 
3398314b673SRoberto Sassu 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
3408314b673SRoberto Sassu 		rc = __vfs_getxattr(dentry, d_backing_inode(dentry),
3418314b673SRoberto Sassu 				    xattr->name, NULL, 0);
3428314b673SRoberto Sassu 		if (rc < 0 && rc == -ENODATA)
3438314b673SRoberto Sassu 			continue;
3448314b673SRoberto Sassu 		else if (rc < 0)
3458314b673SRoberto Sassu 			return rc;
3468314b673SRoberto Sassu 
3478314b673SRoberto Sassu 		switch (type) {
3488314b673SRoberto Sassu 		case 'n':
3498314b673SRoberto Sassu 			size = strlen(xattr->name) + 1;
3508314b673SRoberto Sassu 			if (buffer) {
3518314b673SRoberto Sassu 				if (total_size)
3528314b673SRoberto Sassu 					*(buffer + total_size - 1) = '|';
3538314b673SRoberto Sassu 
3548314b673SRoberto Sassu 				memcpy(buffer + total_size, xattr->name, size);
3558314b673SRoberto Sassu 			}
3568314b673SRoberto Sassu 			break;
3578314b673SRoberto Sassu 		case 'l':
3588314b673SRoberto Sassu 			size = sizeof(u32);
3598314b673SRoberto Sassu 			if (buffer) {
3608314b673SRoberto Sassu 				if (canonical_fmt)
3616b26285fSRoberto Sassu 					rc = (__force int)cpu_to_le32(rc);
3628314b673SRoberto Sassu 
3638314b673SRoberto Sassu 				*(u32 *)(buffer + total_size) = rc;
3648314b673SRoberto Sassu 			}
3658314b673SRoberto Sassu 			break;
3668314b673SRoberto Sassu 		case 'v':
3678314b673SRoberto Sassu 			size = rc;
3688314b673SRoberto Sassu 			if (buffer) {
3698314b673SRoberto Sassu 				rc = __vfs_getxattr(dentry,
3708314b673SRoberto Sassu 					d_backing_inode(dentry), xattr->name,
3718314b673SRoberto Sassu 					buffer + total_size,
3728314b673SRoberto Sassu 					buffer_size - total_size);
3738314b673SRoberto Sassu 				if (rc < 0)
3748314b673SRoberto Sassu 					return rc;
3758314b673SRoberto Sassu 			}
3768314b673SRoberto Sassu 			break;
3778314b673SRoberto Sassu 		default:
3788314b673SRoberto Sassu 			return -EINVAL;
3798314b673SRoberto Sassu 		}
3808314b673SRoberto Sassu 
3818314b673SRoberto Sassu 		total_size += size;
3828314b673SRoberto Sassu 	}
3838314b673SRoberto Sassu 
3848314b673SRoberto Sassu 	return total_size;
3858314b673SRoberto Sassu }
3868314b673SRoberto Sassu 
3878314b673SRoberto Sassu /**
38866dbc325SMimi Zohar  * evm_verifyxattr - verify the integrity of the requested xattr
38966dbc325SMimi Zohar  * @dentry: object of the verify xattr
39066dbc325SMimi Zohar  * @xattr_name: requested xattr
39166dbc325SMimi Zohar  * @xattr_value: requested xattr value
39266dbc325SMimi Zohar  * @xattr_value_len: requested xattr value length
393996e0a97SRoberto Sassu  * @iint: inode integrity metadata
39466dbc325SMimi Zohar  *
39566dbc325SMimi Zohar  * Calculate the HMAC for the given dentry and verify it against the stored
39666dbc325SMimi Zohar  * security.evm xattr. For performance, use the xattr value and length
39766dbc325SMimi Zohar  * previously retrieved to calculate the HMAC.
39866dbc325SMimi Zohar  *
39966dbc325SMimi Zohar  * Returns the xattr integrity status.
40066dbc325SMimi Zohar  *
40166dbc325SMimi Zohar  * This function requires the caller to lock the inode's i_mutex before it
40266dbc325SMimi Zohar  * is executed.
40366dbc325SMimi Zohar  */
evm_verifyxattr(struct dentry * dentry,const char * xattr_name,void * xattr_value,size_t xattr_value_len,struct integrity_iint_cache * iint)40466dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry,
40566dbc325SMimi Zohar 				      const char *xattr_name,
4062960e6cbSDmitry Kasatkin 				      void *xattr_value, size_t xattr_value_len,
4072960e6cbSDmitry Kasatkin 				      struct integrity_iint_cache *iint)
40866dbc325SMimi Zohar {
409ae1ba167SMatthew Garrett 	if (!evm_key_loaded() || !evm_protected_xattr(xattr_name))
41066dbc325SMimi Zohar 		return INTEGRITY_UNKNOWN;
41166dbc325SMimi Zohar 
4122960e6cbSDmitry Kasatkin 	if (!iint) {
413c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
41466dbc325SMimi Zohar 		if (!iint)
41566dbc325SMimi Zohar 			return INTEGRITY_UNKNOWN;
4162960e6cbSDmitry Kasatkin 	}
4172960e6cbSDmitry Kasatkin 	return evm_verify_hmac(dentry, xattr_name, xattr_value,
41866dbc325SMimi Zohar 				 xattr_value_len, iint);
41966dbc325SMimi Zohar }
42066dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr);
42166dbc325SMimi Zohar 
42266dbc325SMimi Zohar /*
4237102ebcdSMimi Zohar  * evm_verify_current_integrity - verify the dentry's metadata integrity
4247102ebcdSMimi Zohar  * @dentry: pointer to the affected dentry
4257102ebcdSMimi Zohar  *
4267102ebcdSMimi Zohar  * Verify and return the dentry's metadata integrity. The exceptions are
4277102ebcdSMimi Zohar  * before EVM is initialized or in 'fix' mode.
4287102ebcdSMimi Zohar  */
evm_verify_current_integrity(struct dentry * dentry)4297102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
4307102ebcdSMimi Zohar {
431c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
4327102ebcdSMimi Zohar 
433ae1ba167SMatthew Garrett 	if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode)
434e11afdbbSStefan Berger 		return INTEGRITY_PASS;
4357102ebcdSMimi Zohar 	return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
4367102ebcdSMimi Zohar }
4377102ebcdSMimi Zohar 
438a924ce0bSMimi Zohar /*
4391886ab01SRoberto Sassu  * evm_xattr_change - check if passed xattr value differs from current value
44039f60c1cSChristian Brauner  * @idmap: idmap of the mount
4411886ab01SRoberto Sassu  * @dentry: pointer to the affected dentry
4421886ab01SRoberto Sassu  * @xattr_name: requested xattr
4431886ab01SRoberto Sassu  * @xattr_value: requested xattr value
4441886ab01SRoberto Sassu  * @xattr_value_len: requested xattr value length
4451886ab01SRoberto Sassu  *
4461886ab01SRoberto Sassu  * Check if passed xattr value differs from current value.
4471886ab01SRoberto Sassu  *
4481886ab01SRoberto Sassu  * Returns 1 if passed xattr value differs from current value, 0 otherwise.
4491886ab01SRoberto Sassu  */
evm_xattr_change(struct mnt_idmap * idmap,struct dentry * dentry,const char * xattr_name,const void * xattr_value,size_t xattr_value_len)45039f60c1cSChristian Brauner static int evm_xattr_change(struct mnt_idmap *idmap,
4511886ab01SRoberto Sassu 			    struct dentry *dentry, const char *xattr_name,
4521886ab01SRoberto Sassu 			    const void *xattr_value, size_t xattr_value_len)
4531886ab01SRoberto Sassu {
4541886ab01SRoberto Sassu 	char *xattr_data = NULL;
4551886ab01SRoberto Sassu 	int rc = 0;
4561886ab01SRoberto Sassu 
4574609e1f1SChristian Brauner 	rc = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr_name, &xattr_data,
4581886ab01SRoberto Sassu 				0, GFP_NOFS);
459f6fbd8cbSPaul Moore 	if (rc < 0) {
460f6fbd8cbSPaul Moore 		rc = 1;
461f6fbd8cbSPaul Moore 		goto out;
462f6fbd8cbSPaul Moore 	}
4631886ab01SRoberto Sassu 
4641886ab01SRoberto Sassu 	if (rc == xattr_value_len)
4651886ab01SRoberto Sassu 		rc = !!memcmp(xattr_value, xattr_data, rc);
4661886ab01SRoberto Sassu 	else
4671886ab01SRoberto Sassu 		rc = 1;
4681886ab01SRoberto Sassu 
469f6fbd8cbSPaul Moore out:
4701886ab01SRoberto Sassu 	kfree(xattr_data);
4711886ab01SRoberto Sassu 	return rc;
4721886ab01SRoberto Sassu }
4731886ab01SRoberto Sassu 
4741886ab01SRoberto Sassu /*
475a924ce0bSMimi Zohar  * evm_protect_xattr - protect the EVM extended attribute
476a924ce0bSMimi Zohar  *
477bf6d0f5dSMimi Zohar  * Prevent security.evm from being modified or removed without the
478bf6d0f5dSMimi Zohar  * necessary permissions or when the existing value is invalid.
479bf6d0f5dSMimi Zohar  *
480bf6d0f5dSMimi Zohar  * The posix xattr acls are 'system' prefixed, which normally would not
481bf6d0f5dSMimi Zohar  * affect security.evm.  An interesting side affect of writing posix xattr
482bf6d0f5dSMimi Zohar  * acls is their modifying of the i_mode, which is included in security.evm.
483bf6d0f5dSMimi Zohar  * For posix xattr acls only, permit security.evm, even if it currently
48450b97748SMatthew Garrett  * doesn't exist, to be updated unless the EVM signature is immutable.
485a924ce0bSMimi Zohar  */
evm_protect_xattr(struct mnt_idmap * idmap,struct dentry * dentry,const char * xattr_name,const void * xattr_value,size_t xattr_value_len)48639f60c1cSChristian Brauner static int evm_protect_xattr(struct mnt_idmap *idmap,
4877e135dc7SRoberto Sassu 			     struct dentry *dentry, const char *xattr_name,
488a924ce0bSMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
489a924ce0bSMimi Zohar {
490a924ce0bSMimi Zohar 	enum integrity_status evm_status;
491a924ce0bSMimi Zohar 
492a924ce0bSMimi Zohar 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
493a924ce0bSMimi Zohar 		if (!capable(CAP_SYS_ADMIN))
494a924ce0bSMimi Zohar 			return -EPERM;
495bf6d0f5dSMimi Zohar 	} else if (!evm_protected_xattr(xattr_name)) {
496bf6d0f5dSMimi Zohar 		if (!posix_xattr_acl(xattr_name))
497a924ce0bSMimi Zohar 			return 0;
498bf6d0f5dSMimi Zohar 		evm_status = evm_verify_current_integrity(dentry);
499bf6d0f5dSMimi Zohar 		if ((evm_status == INTEGRITY_PASS) ||
500566be59aSMimi Zohar 		    (evm_status == INTEGRITY_NOXATTRS))
501bf6d0f5dSMimi Zohar 			return 0;
5029b97b6cdSMimi Zohar 		goto out;
503bf6d0f5dSMimi Zohar 	}
504ae1ba167SMatthew Garrett 
505a924ce0bSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
5063dcbad52SDmitry Kasatkin 	if (evm_status == INTEGRITY_NOXATTRS) {
5073dcbad52SDmitry Kasatkin 		struct integrity_iint_cache *iint;
5083dcbad52SDmitry Kasatkin 
5094a804b8aSRoberto Sassu 		/* Exception if the HMAC is not going to be calculated. */
5104a804b8aSRoberto Sassu 		if (evm_hmac_disabled())
5114a804b8aSRoberto Sassu 			return 0;
5124a804b8aSRoberto Sassu 
513c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
5143dcbad52SDmitry Kasatkin 		if (iint && (iint->flags & IMA_NEW_FILE))
5153dcbad52SDmitry Kasatkin 			return 0;
5165101a185SMimi Zohar 
5175101a185SMimi Zohar 		/* exception for pseudo filesystems */
518fc64005cSAl Viro 		if (dentry->d_sb->s_magic == TMPFS_MAGIC
519fc64005cSAl Viro 		    || dentry->d_sb->s_magic == SYSFS_MAGIC)
5205101a185SMimi Zohar 			return 0;
5215101a185SMimi Zohar 
5225101a185SMimi Zohar 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
5235101a185SMimi Zohar 				    dentry->d_inode, dentry->d_name.name,
5245101a185SMimi Zohar 				    "update_metadata",
5255101a185SMimi Zohar 				    integrity_status_msg[evm_status],
5265101a185SMimi Zohar 				    -EPERM, 0);
5273dcbad52SDmitry Kasatkin 	}
5289b97b6cdSMimi Zohar out:
5294a804b8aSRoberto Sassu 	/* Exception if the HMAC is not going to be calculated. */
5304a804b8aSRoberto Sassu 	if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
5314a804b8aSRoberto Sassu 	    evm_status == INTEGRITY_UNKNOWN))
5324a804b8aSRoberto Sassu 		return 0;
533cdef685bSRoberto Sassu 
534cdef685bSRoberto Sassu 	/*
535cdef685bSRoberto Sassu 	 * Writing other xattrs is safe for portable signatures, as portable
536cdef685bSRoberto Sassu 	 * signatures are immutable and can never be updated.
537cdef685bSRoberto Sassu 	 */
538cdef685bSRoberto Sassu 	if (evm_status == INTEGRITY_FAIL_IMMUTABLE)
539cdef685bSRoberto Sassu 		return 0;
540cdef685bSRoberto Sassu 
5411886ab01SRoberto Sassu 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
54239f60c1cSChristian Brauner 	    !evm_xattr_change(idmap, dentry, xattr_name, xattr_value,
5431886ab01SRoberto Sassu 			      xattr_value_len))
5441886ab01SRoberto Sassu 		return 0;
5451886ab01SRoberto Sassu 
5461886ab01SRoberto Sassu 	if (evm_status != INTEGRITY_PASS &&
5471886ab01SRoberto Sassu 	    evm_status != INTEGRITY_PASS_IMMUTABLE)
548c6f493d6SDavid Howells 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
5499b97b6cdSMimi Zohar 				    dentry->d_name.name, "appraise_metadata",
5509b97b6cdSMimi Zohar 				    integrity_status_msg[evm_status],
5519b97b6cdSMimi Zohar 				    -EPERM, 0);
552a924ce0bSMimi Zohar 	return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
553a924ce0bSMimi Zohar }
554a924ce0bSMimi Zohar 
55566dbc325SMimi Zohar /**
55666dbc325SMimi Zohar  * evm_inode_setxattr - protect the EVM extended attribute
55739f60c1cSChristian Brauner  * @idmap: idmap of the mount
55866dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
55966dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
56066dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
56166dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
56266dbc325SMimi Zohar  *
5632fb1c9a4SMimi Zohar  * Before allowing the 'security.evm' protected xattr to be updated,
5642fb1c9a4SMimi Zohar  * verify the existing value is valid.  As only the kernel should have
5652fb1c9a4SMimi Zohar  * access to the EVM encrypted key needed to calculate the HMAC, prevent
5662fb1c9a4SMimi Zohar  * userspace from writing HMAC value.  Writing 'security.evm' requires
5672fb1c9a4SMimi Zohar  * requires CAP_SYS_ADMIN privileges.
56866dbc325SMimi Zohar  */
evm_inode_setxattr(struct mnt_idmap * idmap,struct dentry * dentry,const char * xattr_name,const void * xattr_value,size_t xattr_value_len)56939f60c1cSChristian Brauner int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
5707e135dc7SRoberto Sassu 		       const char *xattr_name, const void *xattr_value,
5717e135dc7SRoberto Sassu 		       size_t xattr_value_len)
57266dbc325SMimi Zohar {
5732fb1c9a4SMimi Zohar 	const struct evm_ima_xattr_data *xattr_data = xattr_value;
5742fb1c9a4SMimi Zohar 
575ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected xattrs even though
576ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
577ae1ba167SMatthew Garrett 	 */
578ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
579ae1ba167SMatthew Garrett 		return 0;
580ae1ba167SMatthew Garrett 
5813b1deef6SDmitry Kasatkin 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
5823b1deef6SDmitry Kasatkin 		if (!xattr_value_len)
5833b1deef6SDmitry Kasatkin 			return -EINVAL;
58450b97748SMatthew Garrett 		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG &&
58550b97748SMatthew Garrett 		    xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG)
5862fb1c9a4SMimi Zohar 			return -EPERM;
5873b1deef6SDmitry Kasatkin 	}
58839f60c1cSChristian Brauner 	return evm_protect_xattr(idmap, dentry, xattr_name, xattr_value,
58966dbc325SMimi Zohar 				 xattr_value_len);
59066dbc325SMimi Zohar }
59166dbc325SMimi Zohar 
59266dbc325SMimi Zohar /**
59366dbc325SMimi Zohar  * evm_inode_removexattr - protect the EVM extended attribute
59439f60c1cSChristian Brauner  * @idmap: idmap of the mount
59566dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
59666dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
59766dbc325SMimi Zohar  *
5987102ebcdSMimi Zohar  * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
5997102ebcdSMimi Zohar  * the current value is valid.
60066dbc325SMimi Zohar  */
evm_inode_removexattr(struct mnt_idmap * idmap,struct dentry * dentry,const char * xattr_name)60139f60c1cSChristian Brauner int evm_inode_removexattr(struct mnt_idmap *idmap,
6027e135dc7SRoberto Sassu 			  struct dentry *dentry, const char *xattr_name)
60366dbc325SMimi Zohar {
604ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected xattrs even though
605ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
606ae1ba167SMatthew Garrett 	 */
607ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
608ae1ba167SMatthew Garrett 		return 0;
609ae1ba167SMatthew Garrett 
61039f60c1cSChristian Brauner 	return evm_protect_xattr(idmap, dentry, xattr_name, NULL, 0);
61166dbc325SMimi Zohar }
61266dbc325SMimi Zohar 
613e61b135fSChristian Brauner #ifdef CONFIG_FS_POSIX_ACL
evm_inode_set_acl_change(struct mnt_idmap * idmap,struct dentry * dentry,const char * name,struct posix_acl * kacl)614700b7940SChristian Brauner static int evm_inode_set_acl_change(struct mnt_idmap *idmap,
615e61b135fSChristian Brauner 				    struct dentry *dentry, const char *name,
616e61b135fSChristian Brauner 				    struct posix_acl *kacl)
617e61b135fSChristian Brauner {
618e61b135fSChristian Brauner 	int rc;
619e61b135fSChristian Brauner 
620e61b135fSChristian Brauner 	umode_t mode;
621e61b135fSChristian Brauner 	struct inode *inode = d_backing_inode(dentry);
622e61b135fSChristian Brauner 
623e61b135fSChristian Brauner 	if (!kacl)
624e61b135fSChristian Brauner 		return 1;
625e61b135fSChristian Brauner 
626700b7940SChristian Brauner 	rc = posix_acl_update_mode(idmap, inode, &mode, &kacl);
627e61b135fSChristian Brauner 	if (rc || (inode->i_mode != mode))
628e61b135fSChristian Brauner 		return 1;
629e61b135fSChristian Brauner 
630e61b135fSChristian Brauner 	return 0;
631e61b135fSChristian Brauner }
632e61b135fSChristian Brauner #else
evm_inode_set_acl_change(struct mnt_idmap * idmap,struct dentry * dentry,const char * name,struct posix_acl * kacl)633700b7940SChristian Brauner static inline int evm_inode_set_acl_change(struct mnt_idmap *idmap,
634e61b135fSChristian Brauner 					   struct dentry *dentry,
635e61b135fSChristian Brauner 					   const char *name,
636e61b135fSChristian Brauner 					   struct posix_acl *kacl)
637e61b135fSChristian Brauner {
638e61b135fSChristian Brauner 	return 0;
639e61b135fSChristian Brauner }
640e61b135fSChristian Brauner #endif
641e61b135fSChristian Brauner 
642e61b135fSChristian Brauner /**
643e61b135fSChristian Brauner  * evm_inode_set_acl - protect the EVM extended attribute from posix acls
644700b7940SChristian Brauner  * @idmap: idmap of the idmapped mount
645e61b135fSChristian Brauner  * @dentry: pointer to the affected dentry
646e61b135fSChristian Brauner  * @acl_name: name of the posix acl
647e61b135fSChristian Brauner  * @kacl: pointer to the posix acls
648e61b135fSChristian Brauner  *
649e61b135fSChristian Brauner  * Prevent modifying posix acls causing the EVM HMAC to be re-calculated
650e61b135fSChristian Brauner  * and 'security.evm' xattr updated, unless the existing 'security.evm' is
651e61b135fSChristian Brauner  * valid.
652e61b135fSChristian Brauner  */
evm_inode_set_acl(struct mnt_idmap * idmap,struct dentry * dentry,const char * acl_name,struct posix_acl * kacl)653700b7940SChristian Brauner int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
654e61b135fSChristian Brauner 		      const char *acl_name, struct posix_acl *kacl)
655e61b135fSChristian Brauner {
656e61b135fSChristian Brauner 	enum integrity_status evm_status;
657e61b135fSChristian Brauner 
658e61b135fSChristian Brauner 	/* Policy permits modification of the protected xattrs even though
659e61b135fSChristian Brauner 	 * there's no HMAC key loaded
660e61b135fSChristian Brauner 	 */
661e61b135fSChristian Brauner 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
662e61b135fSChristian Brauner 		return 0;
663e61b135fSChristian Brauner 
664e61b135fSChristian Brauner 	evm_status = evm_verify_current_integrity(dentry);
665e61b135fSChristian Brauner 	if ((evm_status == INTEGRITY_PASS) ||
666e61b135fSChristian Brauner 	    (evm_status == INTEGRITY_NOXATTRS))
667e61b135fSChristian Brauner 		return 0;
668e61b135fSChristian Brauner 
669e61b135fSChristian Brauner 	/* Exception if the HMAC is not going to be calculated. */
670e61b135fSChristian Brauner 	if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
671e61b135fSChristian Brauner 	    evm_status == INTEGRITY_UNKNOWN))
672e61b135fSChristian Brauner 		return 0;
673e61b135fSChristian Brauner 
674e61b135fSChristian Brauner 	/*
675e61b135fSChristian Brauner 	 * Writing other xattrs is safe for portable signatures, as portable
676e61b135fSChristian Brauner 	 * signatures are immutable and can never be updated.
677e61b135fSChristian Brauner 	 */
678e61b135fSChristian Brauner 	if (evm_status == INTEGRITY_FAIL_IMMUTABLE)
679e61b135fSChristian Brauner 		return 0;
680e61b135fSChristian Brauner 
681e61b135fSChristian Brauner 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
682700b7940SChristian Brauner 	    !evm_inode_set_acl_change(idmap, dentry, acl_name, kacl))
683e61b135fSChristian Brauner 		return 0;
684e61b135fSChristian Brauner 
68516257cf6SChristian Brauner 	if (evm_status != INTEGRITY_PASS_IMMUTABLE)
686e61b135fSChristian Brauner 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
687e61b135fSChristian Brauner 				    dentry->d_name.name, "appraise_metadata",
688e61b135fSChristian Brauner 				    integrity_status_msg[evm_status],
689e61b135fSChristian Brauner 				    -EPERM, 0);
69016257cf6SChristian Brauner 	return -EPERM;
691e61b135fSChristian Brauner }
692e61b135fSChristian Brauner 
evm_reset_status(struct inode * inode)693523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode)
694523b74b1SDmitry Kasatkin {
695523b74b1SDmitry Kasatkin 	struct integrity_iint_cache *iint;
696523b74b1SDmitry Kasatkin 
697523b74b1SDmitry Kasatkin 	iint = integrity_iint_find(inode);
698523b74b1SDmitry Kasatkin 	if (iint)
699523b74b1SDmitry Kasatkin 		iint->evm_status = INTEGRITY_UNKNOWN;
700523b74b1SDmitry Kasatkin }
701523b74b1SDmitry Kasatkin 
70266dbc325SMimi Zohar /**
703e3ccfe1aSRoberto Sassu  * evm_revalidate_status - report whether EVM status re-validation is necessary
704e3ccfe1aSRoberto Sassu  * @xattr_name: pointer to the affected extended attribute name
705e3ccfe1aSRoberto Sassu  *
706e3ccfe1aSRoberto Sassu  * Report whether callers of evm_verifyxattr() should re-validate the
707e3ccfe1aSRoberto Sassu  * EVM status.
708e3ccfe1aSRoberto Sassu  *
709e3ccfe1aSRoberto Sassu  * Return true if re-validation is necessary, false otherwise.
710e3ccfe1aSRoberto Sassu  */
evm_revalidate_status(const char * xattr_name)711e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name)
712e3ccfe1aSRoberto Sassu {
713e3ccfe1aSRoberto Sassu 	if (!evm_key_loaded())
714e3ccfe1aSRoberto Sassu 		return false;
715e3ccfe1aSRoberto Sassu 
716e3ccfe1aSRoberto Sassu 	/* evm_inode_post_setattr() passes NULL */
717e3ccfe1aSRoberto Sassu 	if (!xattr_name)
718e3ccfe1aSRoberto Sassu 		return true;
719e3ccfe1aSRoberto Sassu 
720e3ccfe1aSRoberto Sassu 	if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) &&
721e3ccfe1aSRoberto Sassu 	    strcmp(xattr_name, XATTR_NAME_EVM))
722e3ccfe1aSRoberto Sassu 		return false;
723e3ccfe1aSRoberto Sassu 
724e3ccfe1aSRoberto Sassu 	return true;
725e3ccfe1aSRoberto Sassu }
726e3ccfe1aSRoberto Sassu 
727e3ccfe1aSRoberto Sassu /**
72866dbc325SMimi Zohar  * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
72966dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
73066dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
73166dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
73266dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
73366dbc325SMimi Zohar  *
73466dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect the change.
73566dbc325SMimi Zohar  *
73666dbc325SMimi Zohar  * No need to take the i_mutex lock here, as this function is called from
73766dbc325SMimi Zohar  * __vfs_setxattr_noperm().  The caller of which has taken the inode's
73866dbc325SMimi Zohar  * i_mutex lock.
73966dbc325SMimi Zohar  */
evm_inode_post_setxattr(struct dentry * dentry,const char * xattr_name,const void * xattr_value,size_t xattr_value_len)74066dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
74166dbc325SMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
74266dbc325SMimi Zohar {
743e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(xattr_name))
74466dbc325SMimi Zohar 		return;
74566dbc325SMimi Zohar 
746523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
747523b74b1SDmitry Kasatkin 
748e3ccfe1aSRoberto Sassu 	if (!strcmp(xattr_name, XATTR_NAME_EVM))
749e3ccfe1aSRoberto Sassu 		return;
750e3ccfe1aSRoberto Sassu 
7514a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
7524a804b8aSRoberto Sassu 		return;
7534a804b8aSRoberto Sassu 
75466dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
75566dbc325SMimi Zohar }
75666dbc325SMimi Zohar 
75766dbc325SMimi Zohar /**
75866dbc325SMimi Zohar  * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
75966dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
76066dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
76166dbc325SMimi Zohar  *
76266dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
7637c51bb00SDmitry Kasatkin  *
7647c51bb00SDmitry Kasatkin  * No need to take the i_mutex lock here, as this function is called from
7657c51bb00SDmitry Kasatkin  * vfs_removexattr() which takes the i_mutex.
76666dbc325SMimi Zohar  */
evm_inode_post_removexattr(struct dentry * dentry,const char * xattr_name)76766dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
76866dbc325SMimi Zohar {
769e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(xattr_name))
77066dbc325SMimi Zohar 		return;
77166dbc325SMimi Zohar 
772523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
773523b74b1SDmitry Kasatkin 
774e3ccfe1aSRoberto Sassu 	if (!strcmp(xattr_name, XATTR_NAME_EVM))
775e3ccfe1aSRoberto Sassu 		return;
776e3ccfe1aSRoberto Sassu 
7774a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
7784a804b8aSRoberto Sassu 		return;
7794a804b8aSRoberto Sassu 
78066dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, NULL, 0);
78166dbc325SMimi Zohar }
78266dbc325SMimi Zohar 
evm_attr_change(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * attr)783c1632a0fSChristian Brauner static int evm_attr_change(struct mnt_idmap *idmap,
7840e363cf3SChristian Brauner 			   struct dentry *dentry, struct iattr *attr)
7851886ab01SRoberto Sassu {
7861886ab01SRoberto Sassu 	struct inode *inode = d_backing_inode(dentry);
7871886ab01SRoberto Sassu 	unsigned int ia_valid = attr->ia_valid;
7881886ab01SRoberto Sassu 
7890dbe12f2SChristian Brauner 	if (!i_uid_needs_update(idmap, attr, inode) &&
7900dbe12f2SChristian Brauner 	    !i_gid_needs_update(idmap, attr, inode) &&
7911886ab01SRoberto Sassu 	    (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode))
7921886ab01SRoberto Sassu 		return 0;
7931886ab01SRoberto Sassu 
7941886ab01SRoberto Sassu 	return 1;
7951886ab01SRoberto Sassu }
7961886ab01SRoberto Sassu 
79766dbc325SMimi Zohar /**
798817b54aaSMimi Zohar  * evm_inode_setattr - prevent updating an invalid EVM extended attribute
799b1de86d4SRoberto Sassu  * @idmap: idmap of the mount
800817b54aaSMimi Zohar  * @dentry: pointer to the affected dentry
801b1de86d4SRoberto Sassu  * @attr: iattr structure containing the new file attributes
80250b97748SMatthew Garrett  *
80350b97748SMatthew Garrett  * Permit update of file attributes when files have a valid EVM signature,
80450b97748SMatthew Garrett  * except in the case of them having an immutable portable signature.
805817b54aaSMimi Zohar  */
evm_inode_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * attr)806c1632a0fSChristian Brauner int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
8070e363cf3SChristian Brauner 		      struct iattr *attr)
808817b54aaSMimi Zohar {
809817b54aaSMimi Zohar 	unsigned int ia_valid = attr->ia_valid;
810817b54aaSMimi Zohar 	enum integrity_status evm_status;
811817b54aaSMimi Zohar 
812ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected attrs even though
813ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
814ae1ba167SMatthew Garrett 	 */
815ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
816ae1ba167SMatthew Garrett 		return 0;
817ae1ba167SMatthew Garrett 
818a924ce0bSMimi Zohar 	if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
819817b54aaSMimi Zohar 		return 0;
820817b54aaSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
821cdef685bSRoberto Sassu 	/*
822cdef685bSRoberto Sassu 	 * Writing attrs is safe for portable signatures, as portable signatures
823cdef685bSRoberto Sassu 	 * are immutable and can never be updated.
824cdef685bSRoberto Sassu 	 */
825566be59aSMimi Zohar 	if ((evm_status == INTEGRITY_PASS) ||
8264a804b8aSRoberto Sassu 	    (evm_status == INTEGRITY_NOXATTRS) ||
827cdef685bSRoberto Sassu 	    (evm_status == INTEGRITY_FAIL_IMMUTABLE) ||
8284a804b8aSRoberto Sassu 	    (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
8294a804b8aSRoberto Sassu 	     evm_status == INTEGRITY_UNKNOWN)))
830566be59aSMimi Zohar 		return 0;
8311886ab01SRoberto Sassu 
8321886ab01SRoberto Sassu 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
833c1632a0fSChristian Brauner 	    !evm_attr_change(idmap, dentry, attr))
8341886ab01SRoberto Sassu 		return 0;
8351886ab01SRoberto Sassu 
836c6f493d6SDavid Howells 	integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
8379b97b6cdSMimi Zohar 			    dentry->d_name.name, "appraise_metadata",
8389b97b6cdSMimi Zohar 			    integrity_status_msg[evm_status], -EPERM, 0);
839566be59aSMimi Zohar 	return -EPERM;
840817b54aaSMimi Zohar }
841817b54aaSMimi Zohar 
842817b54aaSMimi Zohar /**
84366dbc325SMimi Zohar  * evm_inode_post_setattr - update 'security.evm' after modifying metadata
84466dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
84566dbc325SMimi Zohar  * @ia_valid: for the UID and GID status
84666dbc325SMimi Zohar  *
84766dbc325SMimi Zohar  * For now, update the HMAC stored in 'security.evm' to reflect UID/GID
84866dbc325SMimi Zohar  * changes.
84966dbc325SMimi Zohar  *
85066dbc325SMimi Zohar  * This function is called from notify_change(), which expects the caller
85166dbc325SMimi Zohar  * to lock the inode's i_mutex.
85266dbc325SMimi Zohar  */
evm_inode_post_setattr(struct dentry * dentry,int ia_valid)85366dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
85466dbc325SMimi Zohar {
855e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(NULL))
85666dbc325SMimi Zohar 		return;
85766dbc325SMimi Zohar 
858e3ccfe1aSRoberto Sassu 	evm_reset_status(dentry->d_inode);
859e3ccfe1aSRoberto Sassu 
8604a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
8614a804b8aSRoberto Sassu 		return;
8624a804b8aSRoberto Sassu 
86366dbc325SMimi Zohar 	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
86466dbc325SMimi Zohar 		evm_update_evmxattr(dentry, NULL, NULL, 0);
86566dbc325SMimi Zohar }
86666dbc325SMimi Zohar 
867cb723180SMimi Zohar /*
8689eea2904SRoberto Sassu  * evm_inode_init_security - initializes security.evm HMAC value
869cb723180SMimi Zohar  */
evm_inode_init_security(struct inode * inode,struct inode * dir,const struct qstr * qstr,struct xattr * xattrs,int * xattr_count)8706db7d1deSRoberto Sassu int evm_inode_init_security(struct inode *inode, struct inode *dir,
8716db7d1deSRoberto Sassu 			    const struct qstr *qstr, struct xattr *xattrs,
8726db7d1deSRoberto Sassu 			    int *xattr_count)
873cb723180SMimi Zohar {
874650b29dbSThiago Jung Bauermann 	struct evm_xattr *xattr_data;
875*c31288e5SRoberto Sassu 	struct xattr *xattr, *evm_xattr;
876*c31288e5SRoberto Sassu 	bool evm_protected_xattrs = false;
877cb723180SMimi Zohar 	int rc;
878cb723180SMimi Zohar 
879*c31288e5SRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs)
880*c31288e5SRoberto Sassu 		return 0;
881*c31288e5SRoberto Sassu 
882*c31288e5SRoberto Sassu 	/*
883*c31288e5SRoberto Sassu 	 * security_inode_init_security() makes sure that the xattrs array is
884*c31288e5SRoberto Sassu 	 * contiguous, there is enough space for security.evm, and that there is
885*c31288e5SRoberto Sassu 	 * a terminator at the end of the array.
886*c31288e5SRoberto Sassu 	 */
887*c31288e5SRoberto Sassu 	for (xattr = xattrs; xattr->name; xattr++) {
888*c31288e5SRoberto Sassu 		if (evm_protected_xattr(xattr->name))
889*c31288e5SRoberto Sassu 			evm_protected_xattrs = true;
890*c31288e5SRoberto Sassu 	}
891*c31288e5SRoberto Sassu 
892*c31288e5SRoberto Sassu 	/* EVM xattr not needed. */
893*c31288e5SRoberto Sassu 	if (!evm_protected_xattrs)
8945a4730baSMimi Zohar 		return 0;
895cb723180SMimi Zohar 
8966db7d1deSRoberto Sassu 	evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count);
897*c31288e5SRoberto Sassu 	/*
898*c31288e5SRoberto Sassu 	 * Array terminator (xattr name = NULL) must be the first non-filled
899*c31288e5SRoberto Sassu 	 * xattr slot.
900*c31288e5SRoberto Sassu 	 */
901*c31288e5SRoberto Sassu 	WARN_ONCE(evm_xattr != xattr,
902*c31288e5SRoberto Sassu 		  "%s: xattrs terminator is not the first non-filled slot\n",
903*c31288e5SRoberto Sassu 		  __func__);
9046db7d1deSRoberto Sassu 
905cb723180SMimi Zohar 	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
906cb723180SMimi Zohar 	if (!xattr_data)
907cb723180SMimi Zohar 		return -ENOMEM;
908cb723180SMimi Zohar 
909650b29dbSThiago Jung Bauermann 	xattr_data->data.type = EVM_XATTR_HMAC;
9106db7d1deSRoberto Sassu 	rc = evm_init_hmac(inode, xattrs, xattr_data->digest);
911cb723180SMimi Zohar 	if (rc < 0)
912cb723180SMimi Zohar 		goto out;
913cb723180SMimi Zohar 
914cb723180SMimi Zohar 	evm_xattr->value = xattr_data;
915cb723180SMimi Zohar 	evm_xattr->value_len = sizeof(*xattr_data);
9169548906bSTetsuo Handa 	evm_xattr->name = XATTR_EVM_SUFFIX;
917cb723180SMimi Zohar 	return 0;
918cb723180SMimi Zohar out:
919cb723180SMimi Zohar 	kfree(xattr_data);
920cb723180SMimi Zohar 	return rc;
921cb723180SMimi Zohar }
922cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security);
923cb723180SMimi Zohar 
9242ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509
evm_load_x509(void)9252ce523ebSDmitry Kasatkin void __init evm_load_x509(void)
9262ce523ebSDmitry Kasatkin {
92726ddabfeSDmitry Kasatkin 	int rc;
92826ddabfeSDmitry Kasatkin 
92926ddabfeSDmitry Kasatkin 	rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH);
93026ddabfeSDmitry Kasatkin 	if (!rc)
93126ddabfeSDmitry Kasatkin 		evm_initialized |= EVM_INIT_X509;
9322ce523ebSDmitry Kasatkin }
9332ce523ebSDmitry Kasatkin #endif
9342ce523ebSDmitry Kasatkin 
init_evm(void)93566dbc325SMimi Zohar static int __init init_evm(void)
93666dbc325SMimi Zohar {
93766dbc325SMimi Zohar 	int error;
93821af7663SMatthew Garrett 	struct list_head *pos, *q;
93966dbc325SMimi Zohar 
940d3b33679SDmitry Kasatkin 	evm_init_config();
941d3b33679SDmitry Kasatkin 
942f4dc3778SDmitry Kasatkin 	error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
943f4dc3778SDmitry Kasatkin 	if (error)
94421af7663SMatthew Garrett 		goto error;
945f4dc3778SDmitry Kasatkin 
94666dbc325SMimi Zohar 	error = evm_init_secfs();
94766dbc325SMimi Zohar 	if (error < 0) {
94820ee451fSJoe Perches 		pr_info("Error registering secfs\n");
94921af7663SMatthew Garrett 		goto error;
95021af7663SMatthew Garrett 	}
95121af7663SMatthew Garrett 
95221af7663SMatthew Garrett error:
95321af7663SMatthew Garrett 	if (error != 0) {
95421af7663SMatthew Garrett 		if (!list_empty(&evm_config_xattrnames)) {
955c8b37524SYueHaibing 			list_for_each_safe(pos, q, &evm_config_xattrnames)
95621af7663SMatthew Garrett 				list_del(pos);
95721af7663SMatthew Garrett 		}
95821af7663SMatthew Garrett 	}
95921af7663SMatthew Garrett 
960f4dc3778SDmitry Kasatkin 	return error;
96166dbc325SMimi Zohar }
96215647eb3SDmitry Kasatkin 
96366dbc325SMimi Zohar late_initcall(init_evm);
964