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 
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>
2450d34394SIngo Molnar 
25d46eb369SDmitry Kasatkin #include <crypto/hash.h>
265feeb611SMatthew Garrett #include <crypto/hash_info.h>
27613317bdSRyan Ware #include <crypto/algapi.h>
2866dbc325SMimi Zohar #include "evm.h"
2966dbc325SMimi Zohar 
3066dbc325SMimi Zohar int evm_initialized;
3166dbc325SMimi Zohar 
3217d7b0afSHernán Gonzalez static const char * const integrity_status_msg[] = {
33cdef685bSRoberto Sassu 	"pass", "pass_immutable", "fail", "fail_immutable", "no_label",
34cdef685bSRoberto Sassu 	"no_xattrs", "unknown"
359b97b6cdSMimi Zohar };
36d3b33679SDmitry Kasatkin int evm_hmac_attrs;
3766dbc325SMimi Zohar 
38fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = {
398c7a703eSRoberto Sassu 	{.name = XATTR_NAME_SELINUX,
4066dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX
418c7a703eSRoberto Sassu 	 .enabled = true
4266dbc325SMimi Zohar #endif
438c7a703eSRoberto Sassu 	},
448c7a703eSRoberto Sassu 	{.name = XATTR_NAME_SMACK,
4566dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK
468c7a703eSRoberto Sassu 	 .enabled = true
478c7a703eSRoberto Sassu #endif
488c7a703eSRoberto Sassu 	},
498c7a703eSRoberto Sassu 	{.name = XATTR_NAME_SMACKEXEC,
503e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
518c7a703eSRoberto Sassu 	 .enabled = true
523e38df56SDmitry Kasatkin #endif
538c7a703eSRoberto Sassu 	},
548c7a703eSRoberto Sassu 	{.name = XATTR_NAME_SMACKTRANSMUTE,
558c7a703eSRoberto Sassu #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
568c7a703eSRoberto Sassu 	 .enabled = true
5766dbc325SMimi Zohar #endif
588c7a703eSRoberto Sassu 	},
598c7a703eSRoberto Sassu 	{.name = XATTR_NAME_SMACKMMAP,
608c7a703eSRoberto Sassu #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
618c7a703eSRoberto Sassu 	 .enabled = true
628c7a703eSRoberto Sassu #endif
638c7a703eSRoberto Sassu 	},
648c7a703eSRoberto Sassu 	{.name = XATTR_NAME_APPARMOR,
65096b8546SMatthew Garrett #ifdef CONFIG_SECURITY_APPARMOR
668c7a703eSRoberto Sassu 	 .enabled = true
67096b8546SMatthew Garrett #endif
688c7a703eSRoberto Sassu 	},
698c7a703eSRoberto Sassu 	{.name = XATTR_NAME_IMA,
702fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE
718c7a703eSRoberto Sassu 	 .enabled = true
722fe5d6deSMimi Zohar #endif
738c7a703eSRoberto Sassu 	},
748c7a703eSRoberto Sassu 	{.name = XATTR_NAME_CAPS,
758c7a703eSRoberto Sassu 	 .enabled = true
768c7a703eSRoberto Sassu 	},
7766dbc325SMimi Zohar };
7866dbc325SMimi Zohar 
7921af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames);
8021af7663SMatthew Garrett 
8132ba540fSAustin Kim static int evm_fixmode __ro_after_init;
827102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str)
837102ebcdSMimi Zohar {
847102ebcdSMimi Zohar 	if (strncmp(str, "fix", 3) == 0)
857102ebcdSMimi Zohar 		evm_fixmode = 1;
867fe2bb7eSBruno Meneguele 	else
877fe2bb7eSBruno Meneguele 		pr_err("invalid \"%s\" mode", str);
887fe2bb7eSBruno Meneguele 
89f2544f5eSRandy Dunlap 	return 1;
907102ebcdSMimi Zohar }
917102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode);
927102ebcdSMimi Zohar 
93d3b33679SDmitry Kasatkin static void __init evm_init_config(void)
94d3b33679SDmitry Kasatkin {
9521af7663SMatthew Garrett 	int i, xattrs;
9621af7663SMatthew Garrett 
9721af7663SMatthew Garrett 	xattrs = ARRAY_SIZE(evm_config_default_xattrnames);
9821af7663SMatthew Garrett 
9921af7663SMatthew Garrett 	pr_info("Initialising EVM extended attributes:\n");
10021af7663SMatthew Garrett 	for (i = 0; i < xattrs; i++) {
1018c7a703eSRoberto Sassu 		pr_info("%s%s\n", evm_config_default_xattrnames[i].name,
1028c7a703eSRoberto Sassu 			!evm_config_default_xattrnames[i].enabled ?
1038c7a703eSRoberto Sassu 			" (disabled)" : "");
10421af7663SMatthew Garrett 		list_add_tail(&evm_config_default_xattrnames[i].list,
10521af7663SMatthew Garrett 			      &evm_config_xattrnames);
10621af7663SMatthew Garrett 	}
10721af7663SMatthew Garrett 
108d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID
109d3b33679SDmitry Kasatkin 	evm_hmac_attrs |= EVM_ATTR_FSUUID;
110d3b33679SDmitry Kasatkin #endif
111d3b33679SDmitry Kasatkin 	pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs);
112d3b33679SDmitry Kasatkin }
113d3b33679SDmitry Kasatkin 
114ae1ba167SMatthew Garrett static bool evm_key_loaded(void)
115ae1ba167SMatthew Garrett {
116ae1ba167SMatthew Garrett 	return (bool)(evm_initialized & EVM_KEY_MASK);
117ae1ba167SMatthew Garrett }
118ae1ba167SMatthew Garrett 
1194a804b8aSRoberto Sassu /*
1204a804b8aSRoberto Sassu  * This function determines whether or not it is safe to ignore verification
1214a804b8aSRoberto Sassu  * errors, based on the ability of EVM to calculate HMACs. If the HMAC key
1224a804b8aSRoberto Sassu  * is not loaded, and it cannot be loaded in the future due to the
1234a804b8aSRoberto Sassu  * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the
1244a804b8aSRoberto Sassu  * attrs/xattrs being found invalid will not make them valid.
1254a804b8aSRoberto Sassu  */
1264a804b8aSRoberto Sassu static bool evm_hmac_disabled(void)
1274a804b8aSRoberto Sassu {
1284a804b8aSRoberto Sassu 	if (evm_initialized & EVM_INIT_HMAC)
1294a804b8aSRoberto Sassu 		return false;
1304a804b8aSRoberto Sassu 
1314a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_SETUP_COMPLETE))
1324a804b8aSRoberto Sassu 		return false;
1334a804b8aSRoberto Sassu 
1344a804b8aSRoberto Sassu 	return true;
1354a804b8aSRoberto Sassu }
1364a804b8aSRoberto Sassu 
13715647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry)
13815647eb3SDmitry Kasatkin {
139c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
14021af7663SMatthew Garrett 	struct xattr_list *xattr;
14115647eb3SDmitry Kasatkin 	int error;
14215647eb3SDmitry Kasatkin 	int count = 0;
14315647eb3SDmitry Kasatkin 
1445d6c3191SAndreas Gruenbacher 	if (!(inode->i_opflags & IOP_XATTR))
14515647eb3SDmitry Kasatkin 		return -EOPNOTSUPP;
14615647eb3SDmitry Kasatkin 
147770f6058SMadhuparna Bhowmik 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
14821af7663SMatthew Garrett 		error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
14915647eb3SDmitry Kasatkin 		if (error < 0) {
15015647eb3SDmitry Kasatkin 			if (error == -ENODATA)
15115647eb3SDmitry Kasatkin 				continue;
15215647eb3SDmitry Kasatkin 			return error;
15315647eb3SDmitry Kasatkin 		}
15415647eb3SDmitry Kasatkin 		count++;
15515647eb3SDmitry Kasatkin 	}
15615647eb3SDmitry Kasatkin 
15715647eb3SDmitry Kasatkin 	return count;
15815647eb3SDmitry Kasatkin }
15915647eb3SDmitry Kasatkin 
16066dbc325SMimi Zohar /*
16166dbc325SMimi Zohar  * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
16266dbc325SMimi Zohar  *
16366dbc325SMimi Zohar  * Compute the HMAC on the dentry's protected set of extended attributes
1647102ebcdSMimi Zohar  * and compare it against the stored security.evm xattr.
1657102ebcdSMimi Zohar  *
1667102ebcdSMimi Zohar  * For performance:
1677102ebcdSMimi Zohar  * - use the previoulsy retrieved xattr value and length to calculate the
16866dbc325SMimi Zohar  *   HMAC.)
1697102ebcdSMimi Zohar  * - cache the verification result in the iint, when available.
17066dbc325SMimi Zohar  *
17166dbc325SMimi Zohar  * Returns integrity status
17266dbc325SMimi Zohar  */
17366dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry,
17466dbc325SMimi Zohar 					     const char *xattr_name,
17566dbc325SMimi Zohar 					     char *xattr_value,
17666dbc325SMimi Zohar 					     size_t xattr_value_len,
17766dbc325SMimi Zohar 					     struct integrity_iint_cache *iint)
17866dbc325SMimi Zohar {
17915647eb3SDmitry Kasatkin 	struct evm_ima_xattr_data *xattr_data = NULL;
1805feeb611SMatthew Garrett 	struct signature_v2_hdr *hdr;
181566be59aSMimi Zohar 	enum integrity_status evm_status = INTEGRITY_PASS;
1825feeb611SMatthew Garrett 	struct evm_digest digest;
18370946c4aSSascha Hauer 	struct inode *inode;
184cdef685bSRoberto Sassu 	int rc, xattr_len, evm_immutable = 0;
18566dbc325SMimi Zohar 
18650b97748SMatthew Garrett 	if (iint && (iint->evm_status == INTEGRITY_PASS ||
18750b97748SMatthew Garrett 		     iint->evm_status == INTEGRITY_PASS_IMMUTABLE))
18824e0198eSDmitry Kasatkin 		return iint->evm_status;
18966dbc325SMimi Zohar 
1906d38ca01SDmitry Kasatkin 	/* if status is not PASS, try to check again - against -ENOMEM */
1916d38ca01SDmitry Kasatkin 
19215647eb3SDmitry Kasatkin 	/* first need to know the sig type */
193c7c7a1a1STycho Andersen 	rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM,
194c7c7a1a1STycho Andersen 				(char **)&xattr_data, 0, GFP_NOFS);
19515647eb3SDmitry Kasatkin 	if (rc <= 0) {
1961f100979SDmitry Kasatkin 		evm_status = INTEGRITY_FAIL;
1971f100979SDmitry Kasatkin 		if (rc == -ENODATA) {
19815647eb3SDmitry Kasatkin 			rc = evm_find_protected_xattrs(dentry);
19915647eb3SDmitry Kasatkin 			if (rc > 0)
20015647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOLABEL;
20115647eb3SDmitry Kasatkin 			else if (rc == 0)
20215647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOXATTRS; /* new file */
2031f100979SDmitry Kasatkin 		} else if (rc == -EOPNOTSUPP) {
2041f100979SDmitry Kasatkin 			evm_status = INTEGRITY_UNKNOWN;
20515647eb3SDmitry Kasatkin 		}
206566be59aSMimi Zohar 		goto out;
207566be59aSMimi Zohar 	}
20866dbc325SMimi Zohar 
209b1aaab22SDmitry Kasatkin 	xattr_len = rc;
21015647eb3SDmitry Kasatkin 
21115647eb3SDmitry Kasatkin 	/* check value type */
21215647eb3SDmitry Kasatkin 	switch (xattr_data->type) {
21315647eb3SDmitry Kasatkin 	case EVM_XATTR_HMAC:
214650b29dbSThiago Jung Bauermann 		if (xattr_len != sizeof(struct evm_xattr)) {
215b4bfec7fSSeth Forshee 			evm_status = INTEGRITY_FAIL;
216b4bfec7fSSeth Forshee 			goto out;
217b4bfec7fSSeth Forshee 		}
2185feeb611SMatthew Garrett 
2195feeb611SMatthew Garrett 		digest.hdr.algo = HASH_ALGO_SHA1;
22015647eb3SDmitry Kasatkin 		rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
2215feeb611SMatthew Garrett 				   xattr_value_len, &digest);
22215647eb3SDmitry Kasatkin 		if (rc)
22315647eb3SDmitry Kasatkin 			break;
224650b29dbSThiago Jung Bauermann 		rc = crypto_memneq(xattr_data->data, digest.digest,
2255feeb611SMatthew Garrett 				   SHA1_DIGEST_SIZE);
22615647eb3SDmitry Kasatkin 		if (rc)
22715647eb3SDmitry Kasatkin 			rc = -EINVAL;
22815647eb3SDmitry Kasatkin 		break;
22950b97748SMatthew Garrett 	case EVM_XATTR_PORTABLE_DIGSIG:
230cdef685bSRoberto Sassu 		evm_immutable = 1;
231cdef685bSRoberto Sassu 		fallthrough;
232cdef685bSRoberto Sassu 	case EVM_IMA_XATTR_DIGSIG:
233455b6c91SRoberto Sassu 		/* accept xattr with non-empty signature field */
234455b6c91SRoberto Sassu 		if (xattr_len <= sizeof(struct signature_v2_hdr)) {
235455b6c91SRoberto Sassu 			evm_status = INTEGRITY_FAIL;
236455b6c91SRoberto Sassu 			goto out;
237455b6c91SRoberto Sassu 		}
238455b6c91SRoberto Sassu 
2395feeb611SMatthew Garrett 		hdr = (struct signature_v2_hdr *)xattr_data;
2405feeb611SMatthew Garrett 		digest.hdr.algo = hdr->hash_algo;
24115647eb3SDmitry Kasatkin 		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
2425feeb611SMatthew Garrett 				   xattr_value_len, xattr_data->type, &digest);
24315647eb3SDmitry Kasatkin 		if (rc)
24415647eb3SDmitry Kasatkin 			break;
24515647eb3SDmitry Kasatkin 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
246b1aaab22SDmitry Kasatkin 					(const char *)xattr_data, xattr_len,
2475feeb611SMatthew Garrett 					digest.digest, digest.hdr.length);
24815647eb3SDmitry Kasatkin 		if (!rc) {
24970946c4aSSascha Hauer 			inode = d_backing_inode(dentry);
25070946c4aSSascha Hauer 
25150b97748SMatthew Garrett 			if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
25250b97748SMatthew Garrett 				if (iint)
25350b97748SMatthew Garrett 					iint->flags |= EVM_IMMUTABLE_DIGSIG;
25450b97748SMatthew Garrett 				evm_status = INTEGRITY_PASS_IMMUTABLE;
25570946c4aSSascha Hauer 			} else if (!IS_RDONLY(inode) &&
25670946c4aSSascha Hauer 				   !(inode->i_sb->s_readonly_remount) &&
25770946c4aSSascha Hauer 				   !IS_IMMUTABLE(inode)) {
258c2baec7fSDmitry Kasatkin 				evm_update_evmxattr(dentry, xattr_name,
259c2baec7fSDmitry Kasatkin 						    xattr_value,
26015647eb3SDmitry Kasatkin 						    xattr_value_len);
26115647eb3SDmitry Kasatkin 			}
26250b97748SMatthew Garrett 		}
26315647eb3SDmitry Kasatkin 		break;
26415647eb3SDmitry Kasatkin 	default:
26515647eb3SDmitry Kasatkin 		rc = -EINVAL;
26615647eb3SDmitry Kasatkin 		break;
26715647eb3SDmitry Kasatkin 	}
26815647eb3SDmitry Kasatkin 
269cdef685bSRoberto Sassu 	if (rc) {
270cdef685bSRoberto Sassu 		if (rc == -ENODATA)
271cdef685bSRoberto Sassu 			evm_status = INTEGRITY_NOXATTRS;
272cdef685bSRoberto Sassu 		else if (evm_immutable)
273cdef685bSRoberto Sassu 			evm_status = INTEGRITY_FAIL_IMMUTABLE;
274cdef685bSRoberto Sassu 		else
275cdef685bSRoberto Sassu 			evm_status = INTEGRITY_FAIL;
276cdef685bSRoberto Sassu 	}
27787ac3d00SMimi Zohar 	pr_debug("digest: (%d) [%*phN]\n", digest.hdr.length, digest.hdr.length,
27887ac3d00SMimi Zohar 		  digest.digest);
2797102ebcdSMimi Zohar out:
2807102ebcdSMimi Zohar 	if (iint)
2817102ebcdSMimi Zohar 		iint->evm_status = evm_status;
28215647eb3SDmitry Kasatkin 	kfree(xattr_data);
2837102ebcdSMimi Zohar 	return evm_status;
28466dbc325SMimi Zohar }
28566dbc325SMimi Zohar 
2868c7a703eSRoberto Sassu static int evm_protected_xattr_common(const char *req_xattr_name,
2878c7a703eSRoberto Sassu 				      bool all_xattrs)
28866dbc325SMimi Zohar {
28966dbc325SMimi Zohar 	int namelen;
29066dbc325SMimi Zohar 	int found = 0;
29121af7663SMatthew Garrett 	struct xattr_list *xattr;
29266dbc325SMimi Zohar 
29366dbc325SMimi Zohar 	namelen = strlen(req_xattr_name);
294770f6058SMadhuparna Bhowmik 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
2958c7a703eSRoberto Sassu 		if (!all_xattrs && !xattr->enabled)
2968c7a703eSRoberto Sassu 			continue;
2978c7a703eSRoberto Sassu 
29821af7663SMatthew Garrett 		if ((strlen(xattr->name) == namelen)
29921af7663SMatthew Garrett 		    && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
30066dbc325SMimi Zohar 			found = 1;
30166dbc325SMimi Zohar 			break;
30266dbc325SMimi Zohar 		}
303cb723180SMimi Zohar 		if (strncmp(req_xattr_name,
30421af7663SMatthew Garrett 			    xattr->name + XATTR_SECURITY_PREFIX_LEN,
305cb723180SMimi Zohar 			    strlen(req_xattr_name)) == 0) {
306cb723180SMimi Zohar 			found = 1;
307cb723180SMimi Zohar 			break;
308cb723180SMimi Zohar 		}
30966dbc325SMimi Zohar 	}
31021af7663SMatthew Garrett 
31166dbc325SMimi Zohar 	return found;
31266dbc325SMimi Zohar }
31366dbc325SMimi Zohar 
3148c7a703eSRoberto Sassu static int evm_protected_xattr(const char *req_xattr_name)
3158c7a703eSRoberto Sassu {
3168c7a703eSRoberto Sassu 	return evm_protected_xattr_common(req_xattr_name, false);
3178c7a703eSRoberto Sassu }
3188c7a703eSRoberto Sassu 
3198c7a703eSRoberto Sassu int evm_protected_xattr_if_enabled(const char *req_xattr_name)
3208c7a703eSRoberto Sassu {
3218c7a703eSRoberto Sassu 	return evm_protected_xattr_common(req_xattr_name, true);
3228c7a703eSRoberto Sassu }
3238c7a703eSRoberto Sassu 
32466dbc325SMimi Zohar /**
3258314b673SRoberto Sassu  * evm_read_protected_xattrs - read EVM protected xattr names, lengths, values
3268314b673SRoberto Sassu  * @dentry: dentry of the read xattrs
3278314b673SRoberto Sassu  * @inode: inode of the read xattrs
3288314b673SRoberto Sassu  * @buffer: buffer xattr names, lengths or values are copied to
3298314b673SRoberto Sassu  * @buffer_size: size of buffer
3308314b673SRoberto Sassu  * @type: n: names, l: lengths, v: values
3318314b673SRoberto Sassu  * @canonical_fmt: data format (true: little endian, false: native format)
3328314b673SRoberto Sassu  *
3338314b673SRoberto Sassu  * Read protected xattr names (separated by |), lengths (u32) or values for a
3348314b673SRoberto Sassu  * given dentry and return the total size of copied data. If buffer is NULL,
3358314b673SRoberto Sassu  * just return the total size.
3368314b673SRoberto Sassu  *
3378314b673SRoberto Sassu  * Returns the total size on success, a negative value on error.
3388314b673SRoberto Sassu  */
3398314b673SRoberto Sassu int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
3408314b673SRoberto Sassu 			      int buffer_size, char type, bool canonical_fmt)
3418314b673SRoberto Sassu {
3428314b673SRoberto Sassu 	struct xattr_list *xattr;
3438314b673SRoberto Sassu 	int rc, size, total_size = 0;
3448314b673SRoberto Sassu 
3458314b673SRoberto Sassu 	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
3468314b673SRoberto Sassu 		rc = __vfs_getxattr(dentry, d_backing_inode(dentry),
3478314b673SRoberto Sassu 				    xattr->name, NULL, 0);
3488314b673SRoberto Sassu 		if (rc < 0 && rc == -ENODATA)
3498314b673SRoberto Sassu 			continue;
3508314b673SRoberto Sassu 		else if (rc < 0)
3518314b673SRoberto Sassu 			return rc;
3528314b673SRoberto Sassu 
3538314b673SRoberto Sassu 		switch (type) {
3548314b673SRoberto Sassu 		case 'n':
3558314b673SRoberto Sassu 			size = strlen(xattr->name) + 1;
3568314b673SRoberto Sassu 			if (buffer) {
3578314b673SRoberto Sassu 				if (total_size)
3588314b673SRoberto Sassu 					*(buffer + total_size - 1) = '|';
3598314b673SRoberto Sassu 
3608314b673SRoberto Sassu 				memcpy(buffer + total_size, xattr->name, size);
3618314b673SRoberto Sassu 			}
3628314b673SRoberto Sassu 			break;
3638314b673SRoberto Sassu 		case 'l':
3648314b673SRoberto Sassu 			size = sizeof(u32);
3658314b673SRoberto Sassu 			if (buffer) {
3668314b673SRoberto Sassu 				if (canonical_fmt)
3676b26285fSRoberto Sassu 					rc = (__force int)cpu_to_le32(rc);
3688314b673SRoberto Sassu 
3698314b673SRoberto Sassu 				*(u32 *)(buffer + total_size) = rc;
3708314b673SRoberto Sassu 			}
3718314b673SRoberto Sassu 			break;
3728314b673SRoberto Sassu 		case 'v':
3738314b673SRoberto Sassu 			size = rc;
3748314b673SRoberto Sassu 			if (buffer) {
3758314b673SRoberto Sassu 				rc = __vfs_getxattr(dentry,
3768314b673SRoberto Sassu 					d_backing_inode(dentry), xattr->name,
3778314b673SRoberto Sassu 					buffer + total_size,
3788314b673SRoberto Sassu 					buffer_size - total_size);
3798314b673SRoberto Sassu 				if (rc < 0)
3808314b673SRoberto Sassu 					return rc;
3818314b673SRoberto Sassu 			}
3828314b673SRoberto Sassu 			break;
3838314b673SRoberto Sassu 		default:
3848314b673SRoberto Sassu 			return -EINVAL;
3858314b673SRoberto Sassu 		}
3868314b673SRoberto Sassu 
3878314b673SRoberto Sassu 		total_size += size;
3888314b673SRoberto Sassu 	}
3898314b673SRoberto Sassu 
3908314b673SRoberto Sassu 	return total_size;
3918314b673SRoberto Sassu }
3928314b673SRoberto Sassu 
3938314b673SRoberto Sassu /**
39466dbc325SMimi Zohar  * evm_verifyxattr - verify the integrity of the requested xattr
39566dbc325SMimi Zohar  * @dentry: object of the verify xattr
39666dbc325SMimi Zohar  * @xattr_name: requested xattr
39766dbc325SMimi Zohar  * @xattr_value: requested xattr value
39866dbc325SMimi Zohar  * @xattr_value_len: requested xattr value length
39966dbc325SMimi Zohar  *
40066dbc325SMimi Zohar  * Calculate the HMAC for the given dentry and verify it against the stored
40166dbc325SMimi Zohar  * security.evm xattr. For performance, use the xattr value and length
40266dbc325SMimi Zohar  * previously retrieved to calculate the HMAC.
40366dbc325SMimi Zohar  *
40466dbc325SMimi Zohar  * Returns the xattr integrity status.
40566dbc325SMimi Zohar  *
40666dbc325SMimi Zohar  * This function requires the caller to lock the inode's i_mutex before it
40766dbc325SMimi Zohar  * is executed.
40866dbc325SMimi Zohar  */
40966dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry,
41066dbc325SMimi Zohar 				      const char *xattr_name,
4112960e6cbSDmitry Kasatkin 				      void *xattr_value, size_t xattr_value_len,
4122960e6cbSDmitry Kasatkin 				      struct integrity_iint_cache *iint)
41366dbc325SMimi Zohar {
414ae1ba167SMatthew Garrett 	if (!evm_key_loaded() || !evm_protected_xattr(xattr_name))
41566dbc325SMimi Zohar 		return INTEGRITY_UNKNOWN;
41666dbc325SMimi Zohar 
4172960e6cbSDmitry Kasatkin 	if (!iint) {
418c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
41966dbc325SMimi Zohar 		if (!iint)
42066dbc325SMimi Zohar 			return INTEGRITY_UNKNOWN;
4212960e6cbSDmitry Kasatkin 	}
4222960e6cbSDmitry Kasatkin 	return evm_verify_hmac(dentry, xattr_name, xattr_value,
42366dbc325SMimi Zohar 				 xattr_value_len, iint);
42466dbc325SMimi Zohar }
42566dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr);
42666dbc325SMimi Zohar 
42766dbc325SMimi Zohar /*
4287102ebcdSMimi Zohar  * evm_verify_current_integrity - verify the dentry's metadata integrity
4297102ebcdSMimi Zohar  * @dentry: pointer to the affected dentry
4307102ebcdSMimi Zohar  *
4317102ebcdSMimi Zohar  * Verify and return the dentry's metadata integrity. The exceptions are
4327102ebcdSMimi Zohar  * before EVM is initialized or in 'fix' mode.
4337102ebcdSMimi Zohar  */
4347102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
4357102ebcdSMimi Zohar {
436c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
4377102ebcdSMimi Zohar 
438ae1ba167SMatthew Garrett 	if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode)
439e11afdbbSStefan Berger 		return INTEGRITY_PASS;
4407102ebcdSMimi Zohar 	return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
4417102ebcdSMimi Zohar }
4427102ebcdSMimi Zohar 
443a924ce0bSMimi Zohar /*
4441886ab01SRoberto Sassu  * evm_xattr_acl_change - check if passed ACL changes the inode mode
4451886ab01SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
4461886ab01SRoberto Sassu  * @dentry: pointer to the affected dentry
4471886ab01SRoberto Sassu  * @xattr_name: requested xattr
4481886ab01SRoberto Sassu  * @xattr_value: requested xattr value
4491886ab01SRoberto Sassu  * @xattr_value_len: requested xattr value length
4501886ab01SRoberto Sassu  *
4511886ab01SRoberto Sassu  * Check if passed ACL changes the inode mode, which is protected by EVM.
4521886ab01SRoberto Sassu  *
4531886ab01SRoberto Sassu  * Returns 1 if passed ACL causes inode mode change, 0 otherwise.
4541886ab01SRoberto Sassu  */
4551886ab01SRoberto Sassu static int evm_xattr_acl_change(struct user_namespace *mnt_userns,
4561886ab01SRoberto Sassu 				struct dentry *dentry, const char *xattr_name,
4571886ab01SRoberto Sassu 				const void *xattr_value, size_t xattr_value_len)
4581886ab01SRoberto Sassu {
4591886ab01SRoberto Sassu #ifdef CONFIG_FS_POSIX_ACL
4601886ab01SRoberto Sassu 	umode_t mode;
4611886ab01SRoberto Sassu 	struct posix_acl *acl = NULL, *acl_res;
4621886ab01SRoberto Sassu 	struct inode *inode = d_backing_inode(dentry);
4631886ab01SRoberto Sassu 	int rc;
4641886ab01SRoberto Sassu 
4651886ab01SRoberto Sassu 	/*
4661886ab01SRoberto Sassu 	 * user_ns is not relevant here, ACL_USER/ACL_GROUP don't have impact
4671886ab01SRoberto Sassu 	 * on the inode mode (see posix_acl_equiv_mode()).
4681886ab01SRoberto Sassu 	 */
4691886ab01SRoberto Sassu 	acl = posix_acl_from_xattr(&init_user_ns, xattr_value, xattr_value_len);
4701886ab01SRoberto Sassu 	if (IS_ERR_OR_NULL(acl))
4711886ab01SRoberto Sassu 		return 1;
4721886ab01SRoberto Sassu 
4731886ab01SRoberto Sassu 	acl_res = acl;
4741886ab01SRoberto Sassu 	/*
4751886ab01SRoberto Sassu 	 * Passing mnt_userns is necessary to correctly determine the GID in
4761886ab01SRoberto Sassu 	 * an idmapped mount, as the GID is used to clear the setgid bit in
4771886ab01SRoberto Sassu 	 * the inode mode.
4781886ab01SRoberto Sassu 	 */
4791886ab01SRoberto Sassu 	rc = posix_acl_update_mode(mnt_userns, inode, &mode, &acl_res);
4801886ab01SRoberto Sassu 
4811886ab01SRoberto Sassu 	posix_acl_release(acl);
4821886ab01SRoberto Sassu 
4831886ab01SRoberto Sassu 	if (rc)
4841886ab01SRoberto Sassu 		return 1;
4851886ab01SRoberto Sassu 
4861886ab01SRoberto Sassu 	if (inode->i_mode != mode)
4871886ab01SRoberto Sassu 		return 1;
4881886ab01SRoberto Sassu #endif
4891886ab01SRoberto Sassu 	return 0;
4901886ab01SRoberto Sassu }
4911886ab01SRoberto Sassu 
4921886ab01SRoberto Sassu /*
4931886ab01SRoberto Sassu  * evm_xattr_change - check if passed xattr value differs from current value
4941886ab01SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
4951886ab01SRoberto Sassu  * @dentry: pointer to the affected dentry
4961886ab01SRoberto Sassu  * @xattr_name: requested xattr
4971886ab01SRoberto Sassu  * @xattr_value: requested xattr value
4981886ab01SRoberto Sassu  * @xattr_value_len: requested xattr value length
4991886ab01SRoberto Sassu  *
5001886ab01SRoberto Sassu  * Check if passed xattr value differs from current value.
5011886ab01SRoberto Sassu  *
5021886ab01SRoberto Sassu  * Returns 1 if passed xattr value differs from current value, 0 otherwise.
5031886ab01SRoberto Sassu  */
5041886ab01SRoberto Sassu static int evm_xattr_change(struct user_namespace *mnt_userns,
5051886ab01SRoberto Sassu 			    struct dentry *dentry, const char *xattr_name,
5061886ab01SRoberto Sassu 			    const void *xattr_value, size_t xattr_value_len)
5071886ab01SRoberto Sassu {
5081886ab01SRoberto Sassu 	char *xattr_data = NULL;
5091886ab01SRoberto Sassu 	int rc = 0;
5101886ab01SRoberto Sassu 
5111886ab01SRoberto Sassu 	if (posix_xattr_acl(xattr_name))
5121886ab01SRoberto Sassu 		return evm_xattr_acl_change(mnt_userns, dentry, xattr_name,
5131886ab01SRoberto Sassu 					    xattr_value, xattr_value_len);
5141886ab01SRoberto Sassu 
5151886ab01SRoberto Sassu 	rc = vfs_getxattr_alloc(&init_user_ns, dentry, xattr_name, &xattr_data,
5161886ab01SRoberto Sassu 				0, GFP_NOFS);
5171886ab01SRoberto Sassu 	if (rc < 0)
5181886ab01SRoberto Sassu 		return 1;
5191886ab01SRoberto Sassu 
5201886ab01SRoberto Sassu 	if (rc == xattr_value_len)
5211886ab01SRoberto Sassu 		rc = !!memcmp(xattr_value, xattr_data, rc);
5221886ab01SRoberto Sassu 	else
5231886ab01SRoberto Sassu 		rc = 1;
5241886ab01SRoberto Sassu 
5251886ab01SRoberto Sassu 	kfree(xattr_data);
5261886ab01SRoberto Sassu 	return rc;
5271886ab01SRoberto Sassu }
5281886ab01SRoberto Sassu 
5291886ab01SRoberto Sassu /*
530a924ce0bSMimi Zohar  * evm_protect_xattr - protect the EVM extended attribute
531a924ce0bSMimi Zohar  *
532bf6d0f5dSMimi Zohar  * Prevent security.evm from being modified or removed without the
533bf6d0f5dSMimi Zohar  * necessary permissions or when the existing value is invalid.
534bf6d0f5dSMimi Zohar  *
535bf6d0f5dSMimi Zohar  * The posix xattr acls are 'system' prefixed, which normally would not
536bf6d0f5dSMimi Zohar  * affect security.evm.  An interesting side affect of writing posix xattr
537bf6d0f5dSMimi Zohar  * acls is their modifying of the i_mode, which is included in security.evm.
538bf6d0f5dSMimi Zohar  * For posix xattr acls only, permit security.evm, even if it currently
53950b97748SMatthew Garrett  * doesn't exist, to be updated unless the EVM signature is immutable.
540a924ce0bSMimi Zohar  */
5417e135dc7SRoberto Sassu static int evm_protect_xattr(struct user_namespace *mnt_userns,
5427e135dc7SRoberto Sassu 			     struct dentry *dentry, const char *xattr_name,
543a924ce0bSMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
544a924ce0bSMimi Zohar {
545a924ce0bSMimi Zohar 	enum integrity_status evm_status;
546a924ce0bSMimi Zohar 
547a924ce0bSMimi Zohar 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
548a924ce0bSMimi Zohar 		if (!capable(CAP_SYS_ADMIN))
549a924ce0bSMimi Zohar 			return -EPERM;
550bf6d0f5dSMimi Zohar 	} else if (!evm_protected_xattr(xattr_name)) {
551bf6d0f5dSMimi Zohar 		if (!posix_xattr_acl(xattr_name))
552a924ce0bSMimi Zohar 			return 0;
553bf6d0f5dSMimi Zohar 		evm_status = evm_verify_current_integrity(dentry);
554bf6d0f5dSMimi Zohar 		if ((evm_status == INTEGRITY_PASS) ||
555566be59aSMimi Zohar 		    (evm_status == INTEGRITY_NOXATTRS))
556bf6d0f5dSMimi Zohar 			return 0;
5579b97b6cdSMimi Zohar 		goto out;
558bf6d0f5dSMimi Zohar 	}
559ae1ba167SMatthew Garrett 
560a924ce0bSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
5613dcbad52SDmitry Kasatkin 	if (evm_status == INTEGRITY_NOXATTRS) {
5623dcbad52SDmitry Kasatkin 		struct integrity_iint_cache *iint;
5633dcbad52SDmitry Kasatkin 
5644a804b8aSRoberto Sassu 		/* Exception if the HMAC is not going to be calculated. */
5654a804b8aSRoberto Sassu 		if (evm_hmac_disabled())
5664a804b8aSRoberto Sassu 			return 0;
5674a804b8aSRoberto Sassu 
568c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
5693dcbad52SDmitry Kasatkin 		if (iint && (iint->flags & IMA_NEW_FILE))
5703dcbad52SDmitry Kasatkin 			return 0;
5715101a185SMimi Zohar 
5725101a185SMimi Zohar 		/* exception for pseudo filesystems */
573fc64005cSAl Viro 		if (dentry->d_sb->s_magic == TMPFS_MAGIC
574fc64005cSAl Viro 		    || dentry->d_sb->s_magic == SYSFS_MAGIC)
5755101a185SMimi Zohar 			return 0;
5765101a185SMimi Zohar 
5775101a185SMimi Zohar 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
5785101a185SMimi Zohar 				    dentry->d_inode, dentry->d_name.name,
5795101a185SMimi Zohar 				    "update_metadata",
5805101a185SMimi Zohar 				    integrity_status_msg[evm_status],
5815101a185SMimi Zohar 				    -EPERM, 0);
5823dcbad52SDmitry Kasatkin 	}
5839b97b6cdSMimi Zohar out:
5844a804b8aSRoberto Sassu 	/* Exception if the HMAC is not going to be calculated. */
5854a804b8aSRoberto Sassu 	if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
5864a804b8aSRoberto Sassu 	    evm_status == INTEGRITY_UNKNOWN))
5874a804b8aSRoberto Sassu 		return 0;
588cdef685bSRoberto Sassu 
589cdef685bSRoberto Sassu 	/*
590cdef685bSRoberto Sassu 	 * Writing other xattrs is safe for portable signatures, as portable
591cdef685bSRoberto Sassu 	 * signatures are immutable and can never be updated.
592cdef685bSRoberto Sassu 	 */
593cdef685bSRoberto Sassu 	if (evm_status == INTEGRITY_FAIL_IMMUTABLE)
594cdef685bSRoberto Sassu 		return 0;
595cdef685bSRoberto Sassu 
5961886ab01SRoberto Sassu 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
5971886ab01SRoberto Sassu 	    !evm_xattr_change(mnt_userns, dentry, xattr_name, xattr_value,
5981886ab01SRoberto Sassu 			      xattr_value_len))
5991886ab01SRoberto Sassu 		return 0;
6001886ab01SRoberto Sassu 
6011886ab01SRoberto Sassu 	if (evm_status != INTEGRITY_PASS &&
6021886ab01SRoberto Sassu 	    evm_status != INTEGRITY_PASS_IMMUTABLE)
603c6f493d6SDavid Howells 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
6049b97b6cdSMimi Zohar 				    dentry->d_name.name, "appraise_metadata",
6059b97b6cdSMimi Zohar 				    integrity_status_msg[evm_status],
6069b97b6cdSMimi Zohar 				    -EPERM, 0);
607a924ce0bSMimi Zohar 	return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
608a924ce0bSMimi Zohar }
609a924ce0bSMimi Zohar 
61066dbc325SMimi Zohar /**
61166dbc325SMimi Zohar  * evm_inode_setxattr - protect the EVM extended attribute
6127e135dc7SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
61366dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
61466dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
61566dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
61666dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
61766dbc325SMimi Zohar  *
6182fb1c9a4SMimi Zohar  * Before allowing the 'security.evm' protected xattr to be updated,
6192fb1c9a4SMimi Zohar  * verify the existing value is valid.  As only the kernel should have
6202fb1c9a4SMimi Zohar  * access to the EVM encrypted key needed to calculate the HMAC, prevent
6212fb1c9a4SMimi Zohar  * userspace from writing HMAC value.  Writing 'security.evm' requires
6222fb1c9a4SMimi Zohar  * requires CAP_SYS_ADMIN privileges.
62366dbc325SMimi Zohar  */
6247e135dc7SRoberto Sassu int evm_inode_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
6257e135dc7SRoberto Sassu 		       const char *xattr_name, const void *xattr_value,
6267e135dc7SRoberto Sassu 		       size_t xattr_value_len)
62766dbc325SMimi Zohar {
6282fb1c9a4SMimi Zohar 	const struct evm_ima_xattr_data *xattr_data = xattr_value;
6292fb1c9a4SMimi Zohar 
630ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected xattrs even though
631ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
632ae1ba167SMatthew Garrett 	 */
633ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
634ae1ba167SMatthew Garrett 		return 0;
635ae1ba167SMatthew Garrett 
6363b1deef6SDmitry Kasatkin 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
6373b1deef6SDmitry Kasatkin 		if (!xattr_value_len)
6383b1deef6SDmitry Kasatkin 			return -EINVAL;
63950b97748SMatthew Garrett 		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG &&
64050b97748SMatthew Garrett 		    xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG)
6412fb1c9a4SMimi Zohar 			return -EPERM;
6423b1deef6SDmitry Kasatkin 	}
6437e135dc7SRoberto Sassu 	return evm_protect_xattr(mnt_userns, dentry, xattr_name, xattr_value,
64466dbc325SMimi Zohar 				 xattr_value_len);
64566dbc325SMimi Zohar }
64666dbc325SMimi Zohar 
64766dbc325SMimi Zohar /**
64866dbc325SMimi Zohar  * evm_inode_removexattr - protect the EVM extended attribute
6497e135dc7SRoberto Sassu  * @mnt_userns: user namespace of the idmapped mount
65066dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
65166dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
65266dbc325SMimi Zohar  *
6537102ebcdSMimi Zohar  * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
6547102ebcdSMimi Zohar  * the current value is valid.
65566dbc325SMimi Zohar  */
6567e135dc7SRoberto Sassu int evm_inode_removexattr(struct user_namespace *mnt_userns,
6577e135dc7SRoberto Sassu 			  struct dentry *dentry, const char *xattr_name)
65866dbc325SMimi Zohar {
659ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected xattrs even though
660ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
661ae1ba167SMatthew Garrett 	 */
662ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
663ae1ba167SMatthew Garrett 		return 0;
664ae1ba167SMatthew Garrett 
6657e135dc7SRoberto Sassu 	return evm_protect_xattr(mnt_userns, dentry, xattr_name, NULL, 0);
66666dbc325SMimi Zohar }
66766dbc325SMimi Zohar 
668523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode)
669523b74b1SDmitry Kasatkin {
670523b74b1SDmitry Kasatkin 	struct integrity_iint_cache *iint;
671523b74b1SDmitry Kasatkin 
672523b74b1SDmitry Kasatkin 	iint = integrity_iint_find(inode);
673523b74b1SDmitry Kasatkin 	if (iint)
674523b74b1SDmitry Kasatkin 		iint->evm_status = INTEGRITY_UNKNOWN;
675523b74b1SDmitry Kasatkin }
676523b74b1SDmitry Kasatkin 
67766dbc325SMimi Zohar /**
678e3ccfe1aSRoberto Sassu  * evm_revalidate_status - report whether EVM status re-validation is necessary
679e3ccfe1aSRoberto Sassu  * @xattr_name: pointer to the affected extended attribute name
680e3ccfe1aSRoberto Sassu  *
681e3ccfe1aSRoberto Sassu  * Report whether callers of evm_verifyxattr() should re-validate the
682e3ccfe1aSRoberto Sassu  * EVM status.
683e3ccfe1aSRoberto Sassu  *
684e3ccfe1aSRoberto Sassu  * Return true if re-validation is necessary, false otherwise.
685e3ccfe1aSRoberto Sassu  */
686e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name)
687e3ccfe1aSRoberto Sassu {
688e3ccfe1aSRoberto Sassu 	if (!evm_key_loaded())
689e3ccfe1aSRoberto Sassu 		return false;
690e3ccfe1aSRoberto Sassu 
691e3ccfe1aSRoberto Sassu 	/* evm_inode_post_setattr() passes NULL */
692e3ccfe1aSRoberto Sassu 	if (!xattr_name)
693e3ccfe1aSRoberto Sassu 		return true;
694e3ccfe1aSRoberto Sassu 
695e3ccfe1aSRoberto Sassu 	if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) &&
696e3ccfe1aSRoberto Sassu 	    strcmp(xattr_name, XATTR_NAME_EVM))
697e3ccfe1aSRoberto Sassu 		return false;
698e3ccfe1aSRoberto Sassu 
699e3ccfe1aSRoberto Sassu 	return true;
700e3ccfe1aSRoberto Sassu }
701e3ccfe1aSRoberto Sassu 
702e3ccfe1aSRoberto Sassu /**
70366dbc325SMimi Zohar  * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
70466dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
70566dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
70666dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
70766dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
70866dbc325SMimi Zohar  *
70966dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect the change.
71066dbc325SMimi Zohar  *
71166dbc325SMimi Zohar  * No need to take the i_mutex lock here, as this function is called from
71266dbc325SMimi Zohar  * __vfs_setxattr_noperm().  The caller of which has taken the inode's
71366dbc325SMimi Zohar  * i_mutex lock.
71466dbc325SMimi Zohar  */
71566dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
71666dbc325SMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
71766dbc325SMimi Zohar {
718e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(xattr_name))
71966dbc325SMimi Zohar 		return;
72066dbc325SMimi Zohar 
721523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
722523b74b1SDmitry Kasatkin 
723e3ccfe1aSRoberto Sassu 	if (!strcmp(xattr_name, XATTR_NAME_EVM))
724e3ccfe1aSRoberto Sassu 		return;
725e3ccfe1aSRoberto Sassu 
7264a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
7274a804b8aSRoberto Sassu 		return;
7284a804b8aSRoberto Sassu 
72966dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
73066dbc325SMimi Zohar }
73166dbc325SMimi Zohar 
73266dbc325SMimi Zohar /**
73366dbc325SMimi Zohar  * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
73466dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
73566dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
73666dbc325SMimi Zohar  *
73766dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
7387c51bb00SDmitry Kasatkin  *
7397c51bb00SDmitry Kasatkin  * No need to take the i_mutex lock here, as this function is called from
7407c51bb00SDmitry Kasatkin  * vfs_removexattr() which takes the i_mutex.
74166dbc325SMimi Zohar  */
74266dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
74366dbc325SMimi Zohar {
744e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(xattr_name))
74566dbc325SMimi Zohar 		return;
74666dbc325SMimi Zohar 
747523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
748523b74b1SDmitry Kasatkin 
749e3ccfe1aSRoberto Sassu 	if (!strcmp(xattr_name, XATTR_NAME_EVM))
750e3ccfe1aSRoberto Sassu 		return;
751e3ccfe1aSRoberto Sassu 
7524a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
7534a804b8aSRoberto Sassu 		return;
7544a804b8aSRoberto Sassu 
75566dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, NULL, 0);
75666dbc325SMimi Zohar }
75766dbc325SMimi Zohar 
758*0e363cf3SChristian Brauner static int evm_attr_change(struct user_namespace *mnt_userns,
759*0e363cf3SChristian Brauner 			   struct dentry *dentry, struct iattr *attr)
7601886ab01SRoberto Sassu {
7611886ab01SRoberto Sassu 	struct inode *inode = d_backing_inode(dentry);
7621886ab01SRoberto Sassu 	unsigned int ia_valid = attr->ia_valid;
7631886ab01SRoberto Sassu 
76435faf310SChristian Brauner 	if (!i_uid_needs_update(&init_user_ns, attr, inode) &&
76535faf310SChristian Brauner 	    !i_gid_needs_update(&init_user_ns, attr, inode) &&
7661886ab01SRoberto Sassu 	    (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode))
7671886ab01SRoberto Sassu 		return 0;
7681886ab01SRoberto Sassu 
7691886ab01SRoberto Sassu 	return 1;
7701886ab01SRoberto Sassu }
7711886ab01SRoberto Sassu 
77266dbc325SMimi Zohar /**
773817b54aaSMimi Zohar  * evm_inode_setattr - prevent updating an invalid EVM extended attribute
774817b54aaSMimi Zohar  * @dentry: pointer to the affected dentry
77550b97748SMatthew Garrett  *
77650b97748SMatthew Garrett  * Permit update of file attributes when files have a valid EVM signature,
77750b97748SMatthew Garrett  * except in the case of them having an immutable portable signature.
778817b54aaSMimi Zohar  */
779*0e363cf3SChristian Brauner int evm_inode_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
780*0e363cf3SChristian Brauner 		      struct iattr *attr)
781817b54aaSMimi Zohar {
782817b54aaSMimi Zohar 	unsigned int ia_valid = attr->ia_valid;
783817b54aaSMimi Zohar 	enum integrity_status evm_status;
784817b54aaSMimi Zohar 
785ae1ba167SMatthew Garrett 	/* Policy permits modification of the protected attrs even though
786ae1ba167SMatthew Garrett 	 * there's no HMAC key loaded
787ae1ba167SMatthew Garrett 	 */
788ae1ba167SMatthew Garrett 	if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
789ae1ba167SMatthew Garrett 		return 0;
790ae1ba167SMatthew Garrett 
791a924ce0bSMimi Zohar 	if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
792817b54aaSMimi Zohar 		return 0;
793817b54aaSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
794cdef685bSRoberto Sassu 	/*
795cdef685bSRoberto Sassu 	 * Writing attrs is safe for portable signatures, as portable signatures
796cdef685bSRoberto Sassu 	 * are immutable and can never be updated.
797cdef685bSRoberto Sassu 	 */
798566be59aSMimi Zohar 	if ((evm_status == INTEGRITY_PASS) ||
7994a804b8aSRoberto Sassu 	    (evm_status == INTEGRITY_NOXATTRS) ||
800cdef685bSRoberto Sassu 	    (evm_status == INTEGRITY_FAIL_IMMUTABLE) ||
8014a804b8aSRoberto Sassu 	    (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL ||
8024a804b8aSRoberto Sassu 	     evm_status == INTEGRITY_UNKNOWN)))
803566be59aSMimi Zohar 		return 0;
8041886ab01SRoberto Sassu 
8051886ab01SRoberto Sassu 	if (evm_status == INTEGRITY_PASS_IMMUTABLE &&
806*0e363cf3SChristian Brauner 	    !evm_attr_change(mnt_userns, dentry, attr))
8071886ab01SRoberto Sassu 		return 0;
8081886ab01SRoberto Sassu 
809c6f493d6SDavid Howells 	integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
8109b97b6cdSMimi Zohar 			    dentry->d_name.name, "appraise_metadata",
8119b97b6cdSMimi Zohar 			    integrity_status_msg[evm_status], -EPERM, 0);
812566be59aSMimi Zohar 	return -EPERM;
813817b54aaSMimi Zohar }
814817b54aaSMimi Zohar 
815817b54aaSMimi Zohar /**
81666dbc325SMimi Zohar  * evm_inode_post_setattr - update 'security.evm' after modifying metadata
81766dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
81866dbc325SMimi Zohar  * @ia_valid: for the UID and GID status
81966dbc325SMimi Zohar  *
82066dbc325SMimi Zohar  * For now, update the HMAC stored in 'security.evm' to reflect UID/GID
82166dbc325SMimi Zohar  * changes.
82266dbc325SMimi Zohar  *
82366dbc325SMimi Zohar  * This function is called from notify_change(), which expects the caller
82466dbc325SMimi Zohar  * to lock the inode's i_mutex.
82566dbc325SMimi Zohar  */
82666dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
82766dbc325SMimi Zohar {
828e3ccfe1aSRoberto Sassu 	if (!evm_revalidate_status(NULL))
82966dbc325SMimi Zohar 		return;
83066dbc325SMimi Zohar 
831e3ccfe1aSRoberto Sassu 	evm_reset_status(dentry->d_inode);
832e3ccfe1aSRoberto Sassu 
8334a804b8aSRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC))
8344a804b8aSRoberto Sassu 		return;
8354a804b8aSRoberto Sassu 
83666dbc325SMimi Zohar 	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
83766dbc325SMimi Zohar 		evm_update_evmxattr(dentry, NULL, NULL, 0);
83866dbc325SMimi Zohar }
83966dbc325SMimi Zohar 
840cb723180SMimi Zohar /*
8419eea2904SRoberto Sassu  * evm_inode_init_security - initializes security.evm HMAC value
842cb723180SMimi Zohar  */
843cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode,
844cb723180SMimi Zohar 				 const struct xattr *lsm_xattr,
845cb723180SMimi Zohar 				 struct xattr *evm_xattr)
846cb723180SMimi Zohar {
847650b29dbSThiago Jung Bauermann 	struct evm_xattr *xattr_data;
848cb723180SMimi Zohar 	int rc;
849cb723180SMimi Zohar 
8509eea2904SRoberto Sassu 	if (!(evm_initialized & EVM_INIT_HMAC) ||
8519eea2904SRoberto Sassu 	    !evm_protected_xattr(lsm_xattr->name))
8525a4730baSMimi Zohar 		return 0;
853cb723180SMimi Zohar 
854cb723180SMimi Zohar 	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
855cb723180SMimi Zohar 	if (!xattr_data)
856cb723180SMimi Zohar 		return -ENOMEM;
857cb723180SMimi Zohar 
858650b29dbSThiago Jung Bauermann 	xattr_data->data.type = EVM_XATTR_HMAC;
859cb723180SMimi Zohar 	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
860cb723180SMimi Zohar 	if (rc < 0)
861cb723180SMimi Zohar 		goto out;
862cb723180SMimi Zohar 
863cb723180SMimi Zohar 	evm_xattr->value = xattr_data;
864cb723180SMimi Zohar 	evm_xattr->value_len = sizeof(*xattr_data);
8659548906bSTetsuo Handa 	evm_xattr->name = XATTR_EVM_SUFFIX;
866cb723180SMimi Zohar 	return 0;
867cb723180SMimi Zohar out:
868cb723180SMimi Zohar 	kfree(xattr_data);
869cb723180SMimi Zohar 	return rc;
870cb723180SMimi Zohar }
871cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security);
872cb723180SMimi Zohar 
8732ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509
8742ce523ebSDmitry Kasatkin void __init evm_load_x509(void)
8752ce523ebSDmitry Kasatkin {
87626ddabfeSDmitry Kasatkin 	int rc;
87726ddabfeSDmitry Kasatkin 
87826ddabfeSDmitry Kasatkin 	rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH);
87926ddabfeSDmitry Kasatkin 	if (!rc)
88026ddabfeSDmitry Kasatkin 		evm_initialized |= EVM_INIT_X509;
8812ce523ebSDmitry Kasatkin }
8822ce523ebSDmitry Kasatkin #endif
8832ce523ebSDmitry Kasatkin 
88466dbc325SMimi Zohar static int __init init_evm(void)
88566dbc325SMimi Zohar {
88666dbc325SMimi Zohar 	int error;
88721af7663SMatthew Garrett 	struct list_head *pos, *q;
88866dbc325SMimi Zohar 
889d3b33679SDmitry Kasatkin 	evm_init_config();
890d3b33679SDmitry Kasatkin 
891f4dc3778SDmitry Kasatkin 	error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
892f4dc3778SDmitry Kasatkin 	if (error)
89321af7663SMatthew Garrett 		goto error;
894f4dc3778SDmitry Kasatkin 
89566dbc325SMimi Zohar 	error = evm_init_secfs();
89666dbc325SMimi Zohar 	if (error < 0) {
89720ee451fSJoe Perches 		pr_info("Error registering secfs\n");
89821af7663SMatthew Garrett 		goto error;
89921af7663SMatthew Garrett 	}
90021af7663SMatthew Garrett 
90121af7663SMatthew Garrett error:
90221af7663SMatthew Garrett 	if (error != 0) {
90321af7663SMatthew Garrett 		if (!list_empty(&evm_config_xattrnames)) {
904c8b37524SYueHaibing 			list_for_each_safe(pos, q, &evm_config_xattrnames)
90521af7663SMatthew Garrett 				list_del(pos);
90621af7663SMatthew Garrett 		}
90721af7663SMatthew Garrett 	}
90821af7663SMatthew Garrett 
909f4dc3778SDmitry Kasatkin 	return error;
91066dbc325SMimi Zohar }
91115647eb3SDmitry Kasatkin 
91266dbc325SMimi Zohar late_initcall(init_evm);
913