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>
21*1886ab01SRoberto Sassu #include <linux/posix_acl_xattr.h>
2250d34394SIngo Molnar 
23d46eb369SDmitry Kasatkin #include <crypto/hash.h>
245feeb611SMatthew Garrett #include <crypto/hash_info.h>
25613317bdSRyan Ware #include <crypto/algapi.h>
2666dbc325SMimi Zohar #include "evm.h"
2766dbc325SMimi Zohar 
2866dbc325SMimi Zohar int evm_initialized;
2966dbc325SMimi Zohar 
3017d7b0afSHernán Gonzalez static const char * const integrity_status_msg[] = {
31cdef685bSRoberto Sassu 	"pass", "pass_immutable", "fail", "fail_immutable", "no_label",
32cdef685bSRoberto Sassu 	"no_xattrs", "unknown"
339b97b6cdSMimi Zohar };
34d3b33679SDmitry Kasatkin int evm_hmac_attrs;
3566dbc325SMimi Zohar 
36fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = {
3766dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX
3821af7663SMatthew Garrett 	{.name = XATTR_NAME_SELINUX},
3966dbc325SMimi Zohar #endif
4066dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK
4121af7663SMatthew Garrett 	{.name = XATTR_NAME_SMACK},
423e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
4321af7663SMatthew Garrett 	{.name = XATTR_NAME_SMACKEXEC},
4421af7663SMatthew Garrett 	{.name = XATTR_NAME_SMACKTRANSMUTE},
4521af7663SMatthew Garrett 	{.name = XATTR_NAME_SMACKMMAP},
463e38df56SDmitry Kasatkin #endif
4766dbc325SMimi Zohar #endif
48096b8546SMatthew Garrett #ifdef CONFIG_SECURITY_APPARMOR
4921af7663SMatthew Garrett 	{.name = XATTR_NAME_APPARMOR},
50096b8546SMatthew Garrett #endif
512fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE
5221af7663SMatthew Garrett 	{.name = XATTR_NAME_IMA},
532fe5d6deSMimi Zohar #endif
5421af7663SMatthew Garrett 	{.name = XATTR_NAME_CAPS},
5566dbc325SMimi Zohar };
5666dbc325SMimi Zohar 
5721af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames);
5821af7663SMatthew Garrett 
597102ebcdSMimi Zohar static int evm_fixmode;
607102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str)
617102ebcdSMimi Zohar {
627102ebcdSMimi Zohar 	if (strncmp(str, "fix", 3) == 0)
637102ebcdSMimi Zohar 		evm_fixmode = 1;
647fe2bb7eSBruno Meneguele 	else
657fe2bb7eSBruno Meneguele 		pr_err("invalid \"%s\" mode", str);
667fe2bb7eSBruno Meneguele 
677102ebcdSMimi Zohar 	return 0;
687102ebcdSMimi Zohar }
697102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode);
707102ebcdSMimi Zohar 
71d3b33679SDmitry Kasatkin static void __init evm_init_config(void)
72d3b33679SDmitry Kasatkin {
7321af7663SMatthew Garrett 	int i, xattrs;
7421af7663SMatthew Garrett 
7521af7663SMatthew Garrett 	xattrs = ARRAY_SIZE(evm_config_default_xattrnames);
7621af7663SMatthew Garrett 
7721af7663SMatthew Garrett 	pr_info("Initialising EVM extended attributes:\n");
7821af7663SMatthew Garrett 	for (i = 0; i < xattrs; i++) {
7921af7663SMatthew Garrett 		pr_info("%s\n", evm_config_default_xattrnames[i].name);
8021af7663SMatthew Garrett 		list_add_tail(&evm_config_default_xattrnames[i].list,
8121af7663SMatthew Garrett 			      &evm_config_xattrnames);
8221af7663SMatthew Garrett 	}
8321af7663SMatthew Garrett 
84d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID
85d3b33679SDmitry Kasatkin 	evm_hmac_attrs |= EVM_ATTR_FSUUID;
86d3b33679SDmitry Kasatkin #endif
87d3b33679SDmitry Kasatkin 	pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs);
88d3b33679SDmitry Kasatkin }
89d3b33679SDmitry Kasatkin 
90ae1ba167SMatthew Garrett static bool evm_key_loaded(void)
91ae1ba167SMatthew Garrett {
92ae1ba167SMatthew Garrett 	return (bool)(evm_initialized & EVM_KEY_MASK);
93ae1ba167SMatthew Garrett }
94ae1ba167SMatthew Garrett 
954a804b8aSRoberto Sassu /*
964a804b8aSRoberto Sassu  * This function determines whether or not it is safe to ignore verification
974a804b8aSRoberto Sassu  * errors, based on the ability of EVM to calculate HMACs. If the HMAC key
984a804b8aSRoberto Sassu  * is not loaded, and it cannot be loaded in the future due to the
994a804b8aSRoberto Sassu  * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the
1004a804b8aSRoberto Sassu  * attrs/xattrs being found invalid will not make them valid.
1014a804b8aSRoberto Sassu  */
1024a804b8aSRoberto Sassu static bool evm_hmac_disabled(void)
1034a804b8aSRoberto Sassu {
1044a804b8aSRoberto Sassu 	if (evm_initialized & EVM_INIT_HMAC)
1054a804b8aSRoberto Sassu 		return false;
1064a804b8aSRoberto Sassu 
1074a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_SETUP_COMPLETE))
1084a804b8aSRoberto Sassu 		return false;
1094a804b8aSRoberto Sassu 
1104a804b8aSRoberto Sassu 	return true;
1114a804b8aSRoberto Sassu }
1124a804b8aSRoberto Sassu 
11315647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry)
11415647eb3SDmitry Kasatkin {
115c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
11621af7663SMatthew Garrett 	struct xattr_list *xattr;
11715647eb3SDmitry Kasatkin 	int error;
11815647eb3SDmitry Kasatkin 	int count = 0;
11915647eb3SDmitry Kasatkin 
1205d6c3191SAndreas Gruenbacher 	if (!(inode->i_opflags & IOP_XATTR))
12115647eb3SDmitry Kasatkin 		return -EOPNOTSUPP;
12215647eb3SDmitry Kasatkin 
123770f6058SMadhuparna Bhowmik 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
12421af7663SMatthew Garrett 		error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
12515647eb3SDmitry Kasatkin 		if (error < 0) {
12615647eb3SDmitry Kasatkin 			if (error == -ENODATA)
12715647eb3SDmitry Kasatkin 				continue;
12815647eb3SDmitry Kasatkin 			return error;
12915647eb3SDmitry Kasatkin 		}
13015647eb3SDmitry Kasatkin 		count++;
13115647eb3SDmitry Kasatkin 	}
13215647eb3SDmitry Kasatkin 
13315647eb3SDmitry Kasatkin 	return count;
13415647eb3SDmitry Kasatkin }
13515647eb3SDmitry Kasatkin 
13666dbc325SMimi Zohar /*
13766dbc325SMimi Zohar  * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
13866dbc325SMimi Zohar  *
13966dbc325SMimi Zohar  * Compute the HMAC on the dentry's protected set of extended attributes
1407102ebcdSMimi Zohar  * and compare it against the stored security.evm xattr.
1417102ebcdSMimi Zohar  *
1427102ebcdSMimi Zohar  * For performance:
1437102ebcdSMimi Zohar  * - use the previoulsy retrieved xattr value and length to calculate the
14466dbc325SMimi Zohar  *   HMAC.)
1457102ebcdSMimi Zohar  * - cache the verification result in the iint, when available.
14666dbc325SMimi Zohar  *
14766dbc325SMimi Zohar  * Returns integrity status
14866dbc325SMimi Zohar  */
14966dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry,
15066dbc325SMimi Zohar 					     const char *xattr_name,
15166dbc325SMimi Zohar 					     char *xattr_value,
15266dbc325SMimi Zohar 					     size_t xattr_value_len,
15366dbc325SMimi Zohar 					     struct integrity_iint_cache *iint)
15466dbc325SMimi Zohar {
15515647eb3SDmitry Kasatkin 	struct evm_ima_xattr_data *xattr_data = NULL;
1565feeb611SMatthew Garrett 	struct signature_v2_hdr *hdr;
157566be59aSMimi Zohar 	enum integrity_status evm_status = INTEGRITY_PASS;
1585feeb611SMatthew Garrett 	struct evm_digest digest;
15970946c4aSSascha Hauer 	struct inode *inode;
160cdef685bSRoberto Sassu 	int rc, xattr_len, evm_immutable = 0;
16166dbc325SMimi Zohar 
16250b97748SMatthew Garrett 	if (iint && (iint->evm_status == INTEGRITY_PASS ||
16350b97748SMatthew Garrett 		     iint->evm_status == INTEGRITY_PASS_IMMUTABLE))
16424e0198eSDmitry Kasatkin 		return iint->evm_status;
16566dbc325SMimi Zohar 
1666d38ca01SDmitry Kasatkin 	/* if status is not PASS, try to check again - against -ENOMEM */
1676d38ca01SDmitry Kasatkin 
16815647eb3SDmitry Kasatkin 	/* first need to know the sig type */
169c7c7a1a1STycho Andersen 	rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM,
170c7c7a1a1STycho Andersen 				(char **)&xattr_data, 0, GFP_NOFS);
17115647eb3SDmitry Kasatkin 	if (rc <= 0) {
1721f100979SDmitry Kasatkin 		evm_status = INTEGRITY_FAIL;
1731f100979SDmitry Kasatkin 		if (rc == -ENODATA) {
17415647eb3SDmitry Kasatkin 			rc = evm_find_protected_xattrs(dentry);
17515647eb3SDmitry Kasatkin 			if (rc > 0)
17615647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOLABEL;
17715647eb3SDmitry Kasatkin 			else if (rc == 0)
17815647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOXATTRS; /* new file */
1791f100979SDmitry Kasatkin 		} else if (rc == -EOPNOTSUPP) {
1801f100979SDmitry Kasatkin 			evm_status = INTEGRITY_UNKNOWN;
18115647eb3SDmitry Kasatkin 		}
182566be59aSMimi Zohar 		goto out;
183566be59aSMimi Zohar 	}
18466dbc325SMimi Zohar 
185b1aaab22SDmitry Kasatkin 	xattr_len = rc;
18615647eb3SDmitry Kasatkin 
18715647eb3SDmitry Kasatkin 	/* check value type */
18815647eb3SDmitry Kasatkin 	switch (xattr_data->type) {
18915647eb3SDmitry Kasatkin 	case EVM_XATTR_HMAC:
190650b29dbSThiago Jung Bauermann 		if (xattr_len != sizeof(struct evm_xattr)) {
191b4bfec7fSSeth Forshee 			evm_status = INTEGRITY_FAIL;
192b4bfec7fSSeth Forshee 			goto out;
193b4bfec7fSSeth Forshee 		}
1945feeb611SMatthew Garrett 
1955feeb611SMatthew Garrett 		digest.hdr.algo = HASH_ALGO_SHA1;
19615647eb3SDmitry Kasatkin 		rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
1975feeb611SMatthew Garrett 				   xattr_value_len, &digest);
19815647eb3SDmitry Kasatkin 		if (rc)
19915647eb3SDmitry Kasatkin 			break;
200650b29dbSThiago Jung Bauermann 		rc = crypto_memneq(xattr_data->data, digest.digest,
2015feeb611SMatthew Garrett 				   SHA1_DIGEST_SIZE);
20215647eb3SDmitry Kasatkin 		if (rc)
20315647eb3SDmitry Kasatkin 			rc = -EINVAL;
20415647eb3SDmitry Kasatkin 		break;
20550b97748SMatthew Garrett 	case EVM_XATTR_PORTABLE_DIGSIG:
206cdef685bSRoberto Sassu 		evm_immutable = 1;
207cdef685bSRoberto Sassu 		fallthrough;
208cdef685bSRoberto Sassu 	case EVM_IMA_XATTR_DIGSIG:
209455b6c91SRoberto Sassu 		/* accept xattr with non-empty signature field */
210455b6c91SRoberto Sassu 		if (xattr_len <= sizeof(struct signature_v2_hdr)) {
211455b6c91SRoberto Sassu 			evm_status = INTEGRITY_FAIL;
212455b6c91SRoberto Sassu 			goto out;
213455b6c91SRoberto Sassu 		}
214455b6c91SRoberto Sassu 
2155feeb611SMatthew Garrett 		hdr = (struct signature_v2_hdr *)xattr_data;
2165feeb611SMatthew Garrett 		digest.hdr.algo = hdr->hash_algo;
21715647eb3SDmitry Kasatkin 		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
2185feeb611SMatthew Garrett 				   xattr_value_len, xattr_data->type, &digest);
21915647eb3SDmitry Kasatkin 		if (rc)
22015647eb3SDmitry Kasatkin 			break;
22115647eb3SDmitry Kasatkin 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
222b1aaab22SDmitry Kasatkin 					(const char *)xattr_data, xattr_len,
2235feeb611SMatthew Garrett 					digest.digest, digest.hdr.length);
22415647eb3SDmitry Kasatkin 		if (!rc) {
22570946c4aSSascha Hauer 			inode = d_backing_inode(dentry);
22670946c4aSSascha Hauer 
22750b97748SMatthew Garrett 			if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
22850b97748SMatthew Garrett 				if (iint)
22950b97748SMatthew Garrett 					iint->flags |= EVM_IMMUTABLE_DIGSIG;
23050b97748SMatthew Garrett 				evm_status = INTEGRITY_PASS_IMMUTABLE;
23170946c4aSSascha Hauer 			} else if (!IS_RDONLY(inode) &&
23270946c4aSSascha Hauer 				   !(inode->i_sb->s_readonly_remount) &&
23370946c4aSSascha Hauer 				   !IS_IMMUTABLE(inode)) {
234c2baec7fSDmitry Kasatkin 				evm_update_evmxattr(dentry, xattr_name,
235c2baec7fSDmitry Kasatkin 						    xattr_value,
23615647eb3SDmitry Kasatkin 						    xattr_value_len);
23715647eb3SDmitry Kasatkin 			}
23850b97748SMatthew Garrett 		}
23915647eb3SDmitry Kasatkin 		break;
24015647eb3SDmitry Kasatkin 	default:
24115647eb3SDmitry Kasatkin 		rc = -EINVAL;
24215647eb3SDmitry Kasatkin 		break;
24315647eb3SDmitry Kasatkin 	}
24415647eb3SDmitry Kasatkin 
245cdef685bSRoberto Sassu 	if (rc) {
246cdef685bSRoberto Sassu 		if (rc == -ENODATA)
247cdef685bSRoberto Sassu 			evm_status = INTEGRITY_NOXATTRS;
248cdef685bSRoberto Sassu 		else if (evm_immutable)
249cdef685bSRoberto Sassu 			evm_status = INTEGRITY_FAIL_IMMUTABLE;
250cdef685bSRoberto Sassu 		else
251cdef685bSRoberto Sassu 			evm_status = INTEGRITY_FAIL;
252cdef685bSRoberto Sassu 	}
2537102ebcdSMimi Zohar out:
2547102ebcdSMimi Zohar 	if (iint)
2557102ebcdSMimi Zohar 		iint->evm_status = evm_status;
25615647eb3SDmitry Kasatkin 	kfree(xattr_data);
2577102ebcdSMimi Zohar 	return evm_status;
25866dbc325SMimi Zohar }
25966dbc325SMimi Zohar 
26066dbc325SMimi Zohar static int evm_protected_xattr(const char *req_xattr_name)
26166dbc325SMimi Zohar {
26266dbc325SMimi Zohar 	int namelen;
26366dbc325SMimi Zohar 	int found = 0;
26421af7663SMatthew Garrett 	struct xattr_list *xattr;
26566dbc325SMimi Zohar 
26666dbc325SMimi Zohar 	namelen = strlen(req_xattr_name);
267770f6058SMadhuparna Bhowmik 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
26821af7663SMatthew Garrett 		if ((strlen(xattr->name) == namelen)
26921af7663SMatthew Garrett 		    && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
27066dbc325SMimi Zohar 			found = 1;
27166dbc325SMimi Zohar 			break;
27266dbc325SMimi Zohar 		}
273cb723180SMimi Zohar 		if (strncmp(req_xattr_name,
27421af7663SMatthew Garrett 			    xattr->name + XATTR_SECURITY_PREFIX_LEN,
275cb723180SMimi Zohar 			    strlen(req_xattr_name)) == 0) {
276cb723180SMimi Zohar 			found = 1;
277cb723180SMimi Zohar 			break;
278cb723180SMimi Zohar 		}
27966dbc325SMimi Zohar 	}
28021af7663SMatthew Garrett 
28166dbc325SMimi Zohar 	return found;
28266dbc325SMimi Zohar }
28366dbc325SMimi Zohar 
28466dbc325SMimi Zohar /**
28566dbc325SMimi Zohar  * evm_verifyxattr - verify the integrity of the requested xattr
28666dbc325SMimi Zohar  * @dentry: object of the verify xattr
28766dbc325SMimi Zohar  * @xattr_name: requested xattr
28866dbc325SMimi Zohar  * @xattr_value: requested xattr value
28966dbc325SMimi Zohar  * @xattr_value_len: requested xattr value length
29066dbc325SMimi Zohar  *
29166dbc325SMimi Zohar  * Calculate the HMAC for the given dentry and verify it against the stored
29266dbc325SMimi Zohar  * security.evm xattr. For performance, use the xattr value and length
29366dbc325SMimi Zohar  * previously retrieved to calculate the HMAC.
29466dbc325SMimi Zohar  *
29566dbc325SMimi Zohar  * Returns the xattr integrity status.
29666dbc325SMimi Zohar  *
29766dbc325SMimi Zohar  * This function requires the caller to lock the inode's i_mutex before it
29866dbc325SMimi Zohar  * is executed.
29966dbc325SMimi Zohar  */
30066dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry,
30166dbc325SMimi Zohar 				      const char *xattr_name,
3022960e6cbSDmitry Kasatkin 				      void *xattr_value, size_t xattr_value_len,
3032960e6cbSDmitry Kasatkin 				      struct integrity_iint_cache *iint)
30466dbc325SMimi Zohar {
305ae1ba167SMatthew Garrett 	if (!evm_key_loaded() || !evm_protected_xattr(xattr_name))
30666dbc325SMimi Zohar 		return INTEGRITY_UNKNOWN;
30766dbc325SMimi Zohar 
3082960e6cbSDmitry Kasatkin 	if (!iint) {
309c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
31066dbc325SMimi Zohar 		if (!iint)
31166dbc325SMimi Zohar 			return INTEGRITY_UNKNOWN;
3122960e6cbSDmitry Kasatkin 	}
3132960e6cbSDmitry Kasatkin 	return evm_verify_hmac(dentry, xattr_name, xattr_value,
31466dbc325SMimi Zohar 				 xattr_value_len, iint);
31566dbc325SMimi Zohar }
31666dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr);
31766dbc325SMimi Zohar 
31866dbc325SMimi Zohar /*
3197102ebcdSMimi Zohar  * evm_verify_current_integrity - verify the dentry's metadata integrity
3207102ebcdSMimi Zohar  * @dentry: pointer to the affected dentry
3217102ebcdSMimi Zohar  *
3227102ebcdSMimi Zohar  * Verify and return the dentry's metadata integrity. The exceptions are
3237102ebcdSMimi Zohar  * before EVM is initialized or in 'fix' mode.
3247102ebcdSMimi Zohar  */
3257102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
3267102ebcdSMimi Zohar {
327c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
3287102ebcdSMimi Zohar 
329ae1ba167SMatthew Garrett 	if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode)
3307102ebcdSMimi Zohar 		return 0;
3317102ebcdSMimi Zohar 	return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
3327102ebcdSMimi Zohar }
3337102ebcdSMimi Zohar 
334a924ce0bSMimi Zohar /*
335*1886ab01SRoberto Sassu  * evm_xattr_acl_change - check if passed ACL changes the inode mode
336*1886ab01SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
337*1886ab01SRoberto Sassu  * @dentry: pointer to the affected dentry
338*1886ab01SRoberto Sassu  * @xattr_name: requested xattr
339*1886ab01SRoberto Sassu  * @xattr_value: requested xattr value
340*1886ab01SRoberto Sassu  * @xattr_value_len: requested xattr value length
341*1886ab01SRoberto Sassu  *
342*1886ab01SRoberto Sassu  * Check if passed ACL changes the inode mode, which is protected by EVM.
343*1886ab01SRoberto Sassu  *
344*1886ab01SRoberto Sassu  * Returns 1 if passed ACL causes inode mode change, 0 otherwise.
345*1886ab01SRoberto Sassu  */
346*1886ab01SRoberto Sassu static int evm_xattr_acl_change(struct user_namespace *mnt_userns,
347*1886ab01SRoberto Sassu 				struct dentry *dentry, const char *xattr_name,
348*1886ab01SRoberto Sassu 				const void *xattr_value, size_t xattr_value_len)
349*1886ab01SRoberto Sassu {
350*1886ab01SRoberto Sassu #ifdef CONFIG_FS_POSIX_ACL
351*1886ab01SRoberto Sassu 	umode_t mode;
352*1886ab01SRoberto Sassu 	struct posix_acl *acl = NULL, *acl_res;
353*1886ab01SRoberto Sassu 	struct inode *inode = d_backing_inode(dentry);
354*1886ab01SRoberto Sassu 	int rc;
355*1886ab01SRoberto Sassu 
356*1886ab01SRoberto Sassu 	/*
357*1886ab01SRoberto Sassu 	 * user_ns is not relevant here, ACL_USER/ACL_GROUP don't have impact
358*1886ab01SRoberto Sassu 	 * on the inode mode (see posix_acl_equiv_mode()).
359*1886ab01SRoberto Sassu 	 */
360*1886ab01SRoberto Sassu 	acl = posix_acl_from_xattr(&init_user_ns, xattr_value, xattr_value_len);
361*1886ab01SRoberto Sassu 	if (IS_ERR_OR_NULL(acl))
362*1886ab01SRoberto Sassu 		return 1;
363*1886ab01SRoberto Sassu 
364*1886ab01SRoberto Sassu 	acl_res = acl;
365*1886ab01SRoberto Sassu 	/*
366*1886ab01SRoberto Sassu 	 * Passing mnt_userns is necessary to correctly determine the GID in
367*1886ab01SRoberto Sassu 	 * an idmapped mount, as the GID is used to clear the setgid bit in
368*1886ab01SRoberto Sassu 	 * the inode mode.
369*1886ab01SRoberto Sassu 	 */
370*1886ab01SRoberto Sassu 	rc = posix_acl_update_mode(mnt_userns, inode, &mode, &acl_res);
371*1886ab01SRoberto Sassu 
372*1886ab01SRoberto Sassu 	posix_acl_release(acl);
373*1886ab01SRoberto Sassu 
374*1886ab01SRoberto Sassu 	if (rc)
375*1886ab01SRoberto Sassu 		return 1;
376*1886ab01SRoberto Sassu 
377*1886ab01SRoberto Sassu 	if (inode->i_mode != mode)
378*1886ab01SRoberto Sassu 		return 1;
379*1886ab01SRoberto Sassu #endif
380*1886ab01SRoberto Sassu 	return 0;
381*1886ab01SRoberto Sassu }
382*1886ab01SRoberto Sassu 
383*1886ab01SRoberto Sassu /*
384*1886ab01SRoberto Sassu  * evm_xattr_change - check if passed xattr value differs from current value
385*1886ab01SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
386*1886ab01SRoberto Sassu  * @dentry: pointer to the affected dentry
387*1886ab01SRoberto Sassu  * @xattr_name: requested xattr
388*1886ab01SRoberto Sassu  * @xattr_value: requested xattr value
389*1886ab01SRoberto Sassu  * @xattr_value_len: requested xattr value length
390*1886ab01SRoberto Sassu  *
391*1886ab01SRoberto Sassu  * Check if passed xattr value differs from current value.
392*1886ab01SRoberto Sassu  *
393*1886ab01SRoberto Sassu  * Returns 1 if passed xattr value differs from current value, 0 otherwise.
394*1886ab01SRoberto Sassu  */
395*1886ab01SRoberto Sassu static int evm_xattr_change(struct user_namespace *mnt_userns,
396*1886ab01SRoberto Sassu 			    struct dentry *dentry, const char *xattr_name,
397*1886ab01SRoberto Sassu 			    const void *xattr_value, size_t xattr_value_len)
398*1886ab01SRoberto Sassu {
399*1886ab01SRoberto Sassu 	char *xattr_data = NULL;
400*1886ab01SRoberto Sassu 	int rc = 0;
401*1886ab01SRoberto Sassu 
402*1886ab01SRoberto Sassu 	if (posix_xattr_acl(xattr_name))
403*1886ab01SRoberto Sassu 		return evm_xattr_acl_change(mnt_userns, dentry, xattr_name,
404*1886ab01SRoberto Sassu 					    xattr_value, xattr_value_len);
405*1886ab01SRoberto Sassu 
406*1886ab01SRoberto Sassu 	rc = vfs_getxattr_alloc(&init_user_ns, dentry, xattr_name, &xattr_data,
407*1886ab01SRoberto Sassu 				0, GFP_NOFS);
408*1886ab01SRoberto Sassu 	if (rc < 0)
409*1886ab01SRoberto Sassu 		return 1;
410*1886ab01SRoberto Sassu 
411*1886ab01SRoberto Sassu 	if (rc == xattr_value_len)
412*1886ab01SRoberto Sassu 		rc = !!memcmp(xattr_value, xattr_data, rc);
413*1886ab01SRoberto Sassu 	else
414*1886ab01SRoberto Sassu 		rc = 1;
415*1886ab01SRoberto Sassu 
416*1886ab01SRoberto Sassu 	kfree(xattr_data);
417*1886ab01SRoberto Sassu 	return rc;
418*1886ab01SRoberto Sassu }
419*1886ab01SRoberto Sassu 
420*1886ab01SRoberto Sassu /*
421a924ce0bSMimi Zohar  * evm_protect_xattr - protect the EVM extended attribute
422a924ce0bSMimi Zohar  *
423bf6d0f5dSMimi Zohar  * Prevent security.evm from being modified or removed without the
424bf6d0f5dSMimi Zohar  * necessary permissions or when the existing value is invalid.
425bf6d0f5dSMimi Zohar  *
426bf6d0f5dSMimi Zohar  * The posix xattr acls are 'system' prefixed, which normally would not
427bf6d0f5dSMimi Zohar  * affect security.evm.  An interesting side affect of writing posix xattr
428bf6d0f5dSMimi Zohar  * acls is their modifying of the i_mode, which is included in security.evm.
429bf6d0f5dSMimi Zohar  * For posix xattr acls only, permit security.evm, even if it currently
43050b97748SMatthew Garrett  * doesn't exist, to be updated unless the EVM signature is immutable.
431a924ce0bSMimi Zohar  */
4327e135dc7SRoberto Sassu static int evm_protect_xattr(struct user_namespace *mnt_userns,
4337e135dc7SRoberto Sassu 			     struct dentry *dentry, const char *xattr_name,
434a924ce0bSMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
435a924ce0bSMimi Zohar {
436a924ce0bSMimi Zohar 	enum integrity_status evm_status;
437a924ce0bSMimi Zohar 
438a924ce0bSMimi Zohar 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
439a924ce0bSMimi Zohar 		if (!capable(CAP_SYS_ADMIN))
440a924ce0bSMimi Zohar 			return -EPERM;
441bf6d0f5dSMimi Zohar 	} else if (!evm_protected_xattr(xattr_name)) {
442bf6d0f5dSMimi Zohar 		if (!posix_xattr_acl(xattr_name))
443a924ce0bSMimi Zohar 			return 0;
444bf6d0f5dSMimi Zohar 		evm_status = evm_verify_current_integrity(dentry);
445bf6d0f5dSMimi Zohar 		if ((evm_status == INTEGRITY_PASS) ||
446566be59aSMimi Zohar 		    (evm_status == INTEGRITY_NOXATTRS))
447bf6d0f5dSMimi Zohar 			return 0;
4489b97b6cdSMimi Zohar 		goto out;
449bf6d0f5dSMimi Zohar 	}
450ae1ba167SMatthew Garrett 
451a924ce0bSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
4523dcbad52SDmitry Kasatkin 	if (evm_status == INTEGRITY_NOXATTRS) {
4533dcbad52SDmitry Kasatkin 		struct integrity_iint_cache *iint;
4543dcbad52SDmitry Kasatkin 
4554a804b8aSRoberto Sassu 		/* Exception if the HMAC is not going to be calculated. */
4564a804b8aSRoberto Sassu 		if (evm_hmac_disabled())
4574a804b8aSRoberto Sassu 			return 0;
4584a804b8aSRoberto Sassu 
459c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
4603dcbad52SDmitry Kasatkin 		if (iint && (iint->flags & IMA_NEW_FILE))
4613dcbad52SDmitry Kasatkin 			return 0;
4625101a185SMimi Zohar 
4635101a185SMimi Zohar 		/* exception for pseudo filesystems */
464fc64005cSAl Viro 		if (dentry->d_sb->s_magic == TMPFS_MAGIC
465fc64005cSAl Viro 		    || dentry->d_sb->s_magic == SYSFS_MAGIC)
4665101a185SMimi Zohar 			return 0;
4675101a185SMimi Zohar 
4685101a185SMimi Zohar 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
4695101a185SMimi Zohar 				    dentry->d_inode, dentry->d_name.name,
4705101a185SMimi Zohar 				    "update_metadata",
4715101a185SMimi Zohar 				    integrity_status_msg[evm_status],
4725101a185SMimi Zohar 				    -EPERM, 0);
4733dcbad52SDmitry Kasatkin 	}
4749b97b6cdSMimi Zohar out:
4754a804b8aSRoberto Sassu 	/* Exception if the HMAC is not going to be calculated. */
4764a804b8aSRoberto Sassu 	if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
4774a804b8aSRoberto Sassu 	    evm_status == INTEGRITY_UNKNOWN))
4784a804b8aSRoberto Sassu 		return 0;
479cdef685bSRoberto Sassu 
480cdef685bSRoberto Sassu 	/*
481cdef685bSRoberto Sassu 	 * Writing other xattrs is safe for portable signatures, as portable
482cdef685bSRoberto Sassu 	 * signatures are immutable and can never be updated.
483cdef685bSRoberto Sassu 	 */
484cdef685bSRoberto Sassu 	if (evm_status == INTEGRITY_FAIL_IMMUTABLE)
485cdef685bSRoberto Sassu 		return 0;
486cdef685bSRoberto Sassu 
487*1886ab01SRoberto Sassu 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
488*1886ab01SRoberto Sassu 	    !evm_xattr_change(mnt_userns, dentry, xattr_name, xattr_value,
489*1886ab01SRoberto Sassu 			      xattr_value_len))
490*1886ab01SRoberto Sassu 		return 0;
491*1886ab01SRoberto Sassu 
492*1886ab01SRoberto Sassu 	if (evm_status != INTEGRITY_PASS &&
493*1886ab01SRoberto Sassu 	    evm_status != INTEGRITY_PASS_IMMUTABLE)
494c6f493d6SDavid Howells 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
4959b97b6cdSMimi Zohar 				    dentry->d_name.name, "appraise_metadata",
4969b97b6cdSMimi Zohar 				    integrity_status_msg[evm_status],
4979b97b6cdSMimi Zohar 				    -EPERM, 0);
498a924ce0bSMimi Zohar 	return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
499a924ce0bSMimi Zohar }
500a924ce0bSMimi Zohar 
50166dbc325SMimi Zohar /**
50266dbc325SMimi Zohar  * evm_inode_setxattr - protect the EVM extended attribute
5037e135dc7SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
50466dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
50566dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
50666dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
50766dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
50866dbc325SMimi Zohar  *
5092fb1c9a4SMimi Zohar  * Before allowing the 'security.evm' protected xattr to be updated,
5102fb1c9a4SMimi Zohar  * verify the existing value is valid.  As only the kernel should have
5112fb1c9a4SMimi Zohar  * access to the EVM encrypted key needed to calculate the HMAC, prevent
5122fb1c9a4SMimi Zohar  * userspace from writing HMAC value.  Writing 'security.evm' requires
5132fb1c9a4SMimi Zohar  * requires CAP_SYS_ADMIN privileges.
51466dbc325SMimi Zohar  */
5157e135dc7SRoberto Sassu int evm_inode_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
5167e135dc7SRoberto Sassu 		       const char *xattr_name, const void *xattr_value,
5177e135dc7SRoberto Sassu 		       size_t xattr_value_len)
51866dbc325SMimi Zohar {
5192fb1c9a4SMimi Zohar 	const struct evm_ima_xattr_data *xattr_data = xattr_value;
5202fb1c9a4SMimi Zohar 
521ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected xattrs even though
522ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
523ae1ba167SMatthew Garrett 	 */
524ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
525ae1ba167SMatthew Garrett 		return 0;
526ae1ba167SMatthew Garrett 
5273b1deef6SDmitry Kasatkin 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
5283b1deef6SDmitry Kasatkin 		if (!xattr_value_len)
5293b1deef6SDmitry Kasatkin 			return -EINVAL;
53050b97748SMatthew Garrett 		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG &&
53150b97748SMatthew Garrett 		    xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG)
5322fb1c9a4SMimi Zohar 			return -EPERM;
5333b1deef6SDmitry Kasatkin 	}
5347e135dc7SRoberto Sassu 	return evm_protect_xattr(mnt_userns, dentry, xattr_name, xattr_value,
53566dbc325SMimi Zohar 				 xattr_value_len);
53666dbc325SMimi Zohar }
53766dbc325SMimi Zohar 
53866dbc325SMimi Zohar /**
53966dbc325SMimi Zohar  * evm_inode_removexattr - protect the EVM extended attribute
5407e135dc7SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
54166dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
54266dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
54366dbc325SMimi Zohar  *
5447102ebcdSMimi Zohar  * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
5457102ebcdSMimi Zohar  * the current value is valid.
54666dbc325SMimi Zohar  */
5477e135dc7SRoberto Sassu int evm_inode_removexattr(struct user_namespace *mnt_userns,
5487e135dc7SRoberto Sassu 			  struct dentry *dentry, const char *xattr_name)
54966dbc325SMimi Zohar {
550ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected xattrs even though
551ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
552ae1ba167SMatthew Garrett 	 */
553ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
554ae1ba167SMatthew Garrett 		return 0;
555ae1ba167SMatthew Garrett 
5567e135dc7SRoberto Sassu 	return evm_protect_xattr(mnt_userns, dentry, xattr_name, NULL, 0);
55766dbc325SMimi Zohar }
55866dbc325SMimi Zohar 
559523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode)
560523b74b1SDmitry Kasatkin {
561523b74b1SDmitry Kasatkin 	struct integrity_iint_cache *iint;
562523b74b1SDmitry Kasatkin 
563523b74b1SDmitry Kasatkin 	iint = integrity_iint_find(inode);
564523b74b1SDmitry Kasatkin 	if (iint)
565523b74b1SDmitry Kasatkin 		iint->evm_status = INTEGRITY_UNKNOWN;
566523b74b1SDmitry Kasatkin }
567523b74b1SDmitry Kasatkin 
56866dbc325SMimi Zohar /**
569e3ccfe1aSRoberto Sassu  * evm_revalidate_status - report whether EVM status re-validation is necessary
570e3ccfe1aSRoberto Sassu  * @xattr_name: pointer to the affected extended attribute name
571e3ccfe1aSRoberto Sassu  *
572e3ccfe1aSRoberto Sassu  * Report whether callers of evm_verifyxattr() should re-validate the
573e3ccfe1aSRoberto Sassu  * EVM status.
574e3ccfe1aSRoberto Sassu  *
575e3ccfe1aSRoberto Sassu  * Return true if re-validation is necessary, false otherwise.
576e3ccfe1aSRoberto Sassu  */
577e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name)
578e3ccfe1aSRoberto Sassu {
579e3ccfe1aSRoberto Sassu 	if (!evm_key_loaded())
580e3ccfe1aSRoberto Sassu 		return false;
581e3ccfe1aSRoberto Sassu 
582e3ccfe1aSRoberto Sassu 	/* evm_inode_post_setattr() passes NULL */
583e3ccfe1aSRoberto Sassu 	if (!xattr_name)
584e3ccfe1aSRoberto Sassu 		return true;
585e3ccfe1aSRoberto Sassu 
586e3ccfe1aSRoberto Sassu 	if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) &&
587e3ccfe1aSRoberto Sassu 	    strcmp(xattr_name, XATTR_NAME_EVM))
588e3ccfe1aSRoberto Sassu 		return false;
589e3ccfe1aSRoberto Sassu 
590e3ccfe1aSRoberto Sassu 	return true;
591e3ccfe1aSRoberto Sassu }
592e3ccfe1aSRoberto Sassu 
593e3ccfe1aSRoberto Sassu /**
59466dbc325SMimi Zohar  * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
59566dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
59666dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
59766dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
59866dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
59966dbc325SMimi Zohar  *
60066dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect the change.
60166dbc325SMimi Zohar  *
60266dbc325SMimi Zohar  * No need to take the i_mutex lock here, as this function is called from
60366dbc325SMimi Zohar  * __vfs_setxattr_noperm().  The caller of which has taken the inode's
60466dbc325SMimi Zohar  * i_mutex lock.
60566dbc325SMimi Zohar  */
60666dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
60766dbc325SMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
60866dbc325SMimi Zohar {
609e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(xattr_name))
61066dbc325SMimi Zohar 		return;
61166dbc325SMimi Zohar 
612523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
613523b74b1SDmitry Kasatkin 
614e3ccfe1aSRoberto Sassu 	if (!strcmp(xattr_name, XATTR_NAME_EVM))
615e3ccfe1aSRoberto Sassu 		return;
616e3ccfe1aSRoberto Sassu 
6174a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
6184a804b8aSRoberto Sassu 		return;
6194a804b8aSRoberto Sassu 
62066dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
62166dbc325SMimi Zohar }
62266dbc325SMimi Zohar 
62366dbc325SMimi Zohar /**
62466dbc325SMimi Zohar  * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
62566dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
62666dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
62766dbc325SMimi Zohar  *
62866dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
6297c51bb00SDmitry Kasatkin  *
6307c51bb00SDmitry Kasatkin  * No need to take the i_mutex lock here, as this function is called from
6317c51bb00SDmitry Kasatkin  * vfs_removexattr() which takes the i_mutex.
63266dbc325SMimi Zohar  */
63366dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
63466dbc325SMimi Zohar {
635e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(xattr_name))
63666dbc325SMimi Zohar 		return;
63766dbc325SMimi Zohar 
638523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
639523b74b1SDmitry Kasatkin 
640e3ccfe1aSRoberto Sassu 	if (!strcmp(xattr_name, XATTR_NAME_EVM))
641e3ccfe1aSRoberto Sassu 		return;
642e3ccfe1aSRoberto Sassu 
6434a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
6444a804b8aSRoberto Sassu 		return;
6454a804b8aSRoberto Sassu 
64666dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, NULL, 0);
64766dbc325SMimi Zohar }
64866dbc325SMimi Zohar 
649*1886ab01SRoberto Sassu static int evm_attr_change(struct dentry *dentry, struct iattr *attr)
650*1886ab01SRoberto Sassu {
651*1886ab01SRoberto Sassu 	struct inode *inode = d_backing_inode(dentry);
652*1886ab01SRoberto Sassu 	unsigned int ia_valid = attr->ia_valid;
653*1886ab01SRoberto Sassu 
654*1886ab01SRoberto Sassu 	if ((!(ia_valid & ATTR_UID) || uid_eq(attr->ia_uid, inode->i_uid)) &&
655*1886ab01SRoberto Sassu 	    (!(ia_valid & ATTR_GID) || gid_eq(attr->ia_gid, inode->i_gid)) &&
656*1886ab01SRoberto Sassu 	    (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode))
657*1886ab01SRoberto Sassu 		return 0;
658*1886ab01SRoberto Sassu 
659*1886ab01SRoberto Sassu 	return 1;
660*1886ab01SRoberto Sassu }
661*1886ab01SRoberto Sassu 
66266dbc325SMimi Zohar /**
663817b54aaSMimi Zohar  * evm_inode_setattr - prevent updating an invalid EVM extended attribute
664817b54aaSMimi Zohar  * @dentry: pointer to the affected dentry
66550b97748SMatthew Garrett  *
66650b97748SMatthew Garrett  * Permit update of file attributes when files have a valid EVM signature,
66750b97748SMatthew Garrett  * except in the case of them having an immutable portable signature.
668817b54aaSMimi Zohar  */
669817b54aaSMimi Zohar int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
670817b54aaSMimi Zohar {
671817b54aaSMimi Zohar 	unsigned int ia_valid = attr->ia_valid;
672817b54aaSMimi Zohar 	enum integrity_status evm_status;
673817b54aaSMimi Zohar 
674ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected attrs even though
675ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
676ae1ba167SMatthew Garrett 	 */
677ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
678ae1ba167SMatthew Garrett 		return 0;
679ae1ba167SMatthew Garrett 
680a924ce0bSMimi Zohar 	if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
681817b54aaSMimi Zohar 		return 0;
682817b54aaSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
683cdef685bSRoberto Sassu 	/*
684cdef685bSRoberto Sassu 	 * Writing attrs is safe for portable signatures, as portable signatures
685cdef685bSRoberto Sassu 	 * are immutable and can never be updated.
686cdef685bSRoberto Sassu 	 */
687566be59aSMimi Zohar 	if ((evm_status == INTEGRITY_PASS) ||
6884a804b8aSRoberto Sassu 	    (evm_status == INTEGRITY_NOXATTRS) ||
689cdef685bSRoberto Sassu 	    (evm_status == INTEGRITY_FAIL_IMMUTABLE) ||
6904a804b8aSRoberto Sassu 	    (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
6914a804b8aSRoberto Sassu 	     evm_status == INTEGRITY_UNKNOWN)))
692566be59aSMimi Zohar 		return 0;
693*1886ab01SRoberto Sassu 
694*1886ab01SRoberto Sassu 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
695*1886ab01SRoberto Sassu 	    !evm_attr_change(dentry, attr))
696*1886ab01SRoberto Sassu 		return 0;
697*1886ab01SRoberto Sassu 
698c6f493d6SDavid Howells 	integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
6999b97b6cdSMimi Zohar 			    dentry->d_name.name, "appraise_metadata",
7009b97b6cdSMimi Zohar 			    integrity_status_msg[evm_status], -EPERM, 0);
701566be59aSMimi Zohar 	return -EPERM;
702817b54aaSMimi Zohar }
703817b54aaSMimi Zohar 
704817b54aaSMimi Zohar /**
70566dbc325SMimi Zohar  * evm_inode_post_setattr - update 'security.evm' after modifying metadata
70666dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
70766dbc325SMimi Zohar  * @ia_valid: for the UID and GID status
70866dbc325SMimi Zohar  *
70966dbc325SMimi Zohar  * For now, update the HMAC stored in 'security.evm' to reflect UID/GID
71066dbc325SMimi Zohar  * changes.
71166dbc325SMimi Zohar  *
71266dbc325SMimi Zohar  * This function is called from notify_change(), which expects the caller
71366dbc325SMimi Zohar  * to lock the inode's i_mutex.
71466dbc325SMimi Zohar  */
71566dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
71666dbc325SMimi Zohar {
717e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(NULL))
71866dbc325SMimi Zohar 		return;
71966dbc325SMimi Zohar 
720e3ccfe1aSRoberto Sassu 	evm_reset_status(dentry->d_inode);
721e3ccfe1aSRoberto Sassu 
7224a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
7234a804b8aSRoberto Sassu 		return;
7244a804b8aSRoberto Sassu 
72566dbc325SMimi Zohar 	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
72666dbc325SMimi Zohar 		evm_update_evmxattr(dentry, NULL, NULL, 0);
72766dbc325SMimi Zohar }
72866dbc325SMimi Zohar 
729cb723180SMimi Zohar /*
7309eea2904SRoberto Sassu  * evm_inode_init_security - initializes security.evm HMAC value
731cb723180SMimi Zohar  */
732cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode,
733cb723180SMimi Zohar 				 const struct xattr *lsm_xattr,
734cb723180SMimi Zohar 				 struct xattr *evm_xattr)
735cb723180SMimi Zohar {
736650b29dbSThiago Jung Bauermann 	struct evm_xattr *xattr_data;
737cb723180SMimi Zohar 	int rc;
738cb723180SMimi Zohar 
7399eea2904SRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC) ||
7409eea2904SRoberto Sassu 	    !evm_protected_xattr(lsm_xattr->name))
7415a4730baSMimi Zohar 		return 0;
742cb723180SMimi Zohar 
743cb723180SMimi Zohar 	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
744cb723180SMimi Zohar 	if (!xattr_data)
745cb723180SMimi Zohar 		return -ENOMEM;
746cb723180SMimi Zohar 
747650b29dbSThiago Jung Bauermann 	xattr_data->data.type = EVM_XATTR_HMAC;
748cb723180SMimi Zohar 	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
749cb723180SMimi Zohar 	if (rc < 0)
750cb723180SMimi Zohar 		goto out;
751cb723180SMimi Zohar 
752cb723180SMimi Zohar 	evm_xattr->value = xattr_data;
753cb723180SMimi Zohar 	evm_xattr->value_len = sizeof(*xattr_data);
7549548906bSTetsuo Handa 	evm_xattr->name = XATTR_EVM_SUFFIX;
755cb723180SMimi Zohar 	return 0;
756cb723180SMimi Zohar out:
757cb723180SMimi Zohar 	kfree(xattr_data);
758cb723180SMimi Zohar 	return rc;
759cb723180SMimi Zohar }
760cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security);
761cb723180SMimi Zohar 
7622ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509
7632ce523ebSDmitry Kasatkin void __init evm_load_x509(void)
7642ce523ebSDmitry Kasatkin {
76526ddabfeSDmitry Kasatkin 	int rc;
76626ddabfeSDmitry Kasatkin 
76726ddabfeSDmitry Kasatkin 	rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH);
76826ddabfeSDmitry Kasatkin 	if (!rc)
76926ddabfeSDmitry Kasatkin 		evm_initialized |= EVM_INIT_X509;
7702ce523ebSDmitry Kasatkin }
7712ce523ebSDmitry Kasatkin #endif
7722ce523ebSDmitry Kasatkin 
77366dbc325SMimi Zohar static int __init init_evm(void)
77466dbc325SMimi Zohar {
77566dbc325SMimi Zohar 	int error;
77621af7663SMatthew Garrett 	struct list_head *pos, *q;
77766dbc325SMimi Zohar 
778d3b33679SDmitry Kasatkin 	evm_init_config();
779d3b33679SDmitry Kasatkin 
780f4dc3778SDmitry Kasatkin 	error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
781f4dc3778SDmitry Kasatkin 	if (error)
78221af7663SMatthew Garrett 		goto error;
783f4dc3778SDmitry Kasatkin 
78466dbc325SMimi Zohar 	error = evm_init_secfs();
78566dbc325SMimi Zohar 	if (error < 0) {
78620ee451fSJoe Perches 		pr_info("Error registering secfs\n");
78721af7663SMatthew Garrett 		goto error;
78821af7663SMatthew Garrett 	}
78921af7663SMatthew Garrett 
79021af7663SMatthew Garrett error:
79121af7663SMatthew Garrett 	if (error != 0) {
79221af7663SMatthew Garrett 		if (!list_empty(&evm_config_xattrnames)) {
793c8b37524SYueHaibing 			list_for_each_safe(pos, q, &evm_config_xattrnames)
79421af7663SMatthew Garrett 				list_del(pos);
79521af7663SMatthew Garrett 		}
79621af7663SMatthew Garrett 	}
79721af7663SMatthew Garrett 
798f4dc3778SDmitry Kasatkin 	return error;
79966dbc325SMimi Zohar }
80015647eb3SDmitry Kasatkin 
80166dbc325SMimi Zohar late_initcall(init_evm);
802