166dbc325SMimi Zohar /*
266dbc325SMimi Zohar  * Copyright (C) 2005-2010 IBM Corporation
366dbc325SMimi Zohar  *
466dbc325SMimi Zohar  * Author:
566dbc325SMimi Zohar  * Mimi Zohar <zohar@us.ibm.com>
666dbc325SMimi Zohar  * Kylene Hall <kjhall@us.ibm.com>
766dbc325SMimi Zohar  *
866dbc325SMimi Zohar  * This program is free software; you can redistribute it and/or modify
966dbc325SMimi Zohar  * it under the terms of the GNU General Public License as published by
1066dbc325SMimi Zohar  * the Free Software Foundation, version 2 of the License.
1166dbc325SMimi Zohar  *
1266dbc325SMimi Zohar  * File: evm_main.c
1366dbc325SMimi Zohar  *	implements evm_inode_setxattr, evm_inode_post_setxattr,
1466dbc325SMimi Zohar  *	evm_inode_removexattr, and evm_verifyxattr
1566dbc325SMimi Zohar  */
1666dbc325SMimi Zohar 
1720ee451fSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1820ee451fSJoe Perches 
1966dbc325SMimi Zohar #include <linux/module.h>
2066dbc325SMimi Zohar #include <linux/crypto.h>
219b97b6cdSMimi Zohar #include <linux/audit.h>
2266dbc325SMimi Zohar #include <linux/xattr.h>
2366dbc325SMimi Zohar #include <linux/integrity.h>
243e1be52dSMimi Zohar #include <linux/evm.h>
25d46eb369SDmitry Kasatkin #include <crypto/hash.h>
26613317bdSRyan Ware #include <crypto/algapi.h>
2766dbc325SMimi Zohar #include "evm.h"
2866dbc325SMimi Zohar 
2966dbc325SMimi Zohar int evm_initialized;
3066dbc325SMimi Zohar 
319b97b6cdSMimi Zohar static char *integrity_status_msg[] = {
329b97b6cdSMimi Zohar 	"pass", "fail", "no_label", "no_xattrs", "unknown"
339b97b6cdSMimi Zohar };
3466dbc325SMimi Zohar char *evm_hmac = "hmac(sha1)";
3515647eb3SDmitry Kasatkin char *evm_hash = "sha1";
36d3b33679SDmitry Kasatkin int evm_hmac_attrs;
3766dbc325SMimi Zohar 
3866dbc325SMimi Zohar char *evm_config_xattrnames[] = {
3966dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX
4066dbc325SMimi Zohar 	XATTR_NAME_SELINUX,
4166dbc325SMimi Zohar #endif
4266dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK
4366dbc325SMimi Zohar 	XATTR_NAME_SMACK,
443e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
453e38df56SDmitry Kasatkin 	XATTR_NAME_SMACKEXEC,
463e38df56SDmitry Kasatkin 	XATTR_NAME_SMACKTRANSMUTE,
473e38df56SDmitry Kasatkin 	XATTR_NAME_SMACKMMAP,
483e38df56SDmitry Kasatkin #endif
4966dbc325SMimi Zohar #endif
502fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE
512fe5d6deSMimi Zohar 	XATTR_NAME_IMA,
522fe5d6deSMimi Zohar #endif
5366dbc325SMimi Zohar 	XATTR_NAME_CAPS,
5466dbc325SMimi Zohar 	NULL
5566dbc325SMimi Zohar };
5666dbc325SMimi Zohar 
577102ebcdSMimi Zohar static int evm_fixmode;
587102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str)
597102ebcdSMimi Zohar {
607102ebcdSMimi Zohar 	if (strncmp(str, "fix", 3) == 0)
617102ebcdSMimi Zohar 		evm_fixmode = 1;
627102ebcdSMimi Zohar 	return 0;
637102ebcdSMimi Zohar }
647102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode);
657102ebcdSMimi Zohar 
66d3b33679SDmitry Kasatkin static void __init evm_init_config(void)
67d3b33679SDmitry Kasatkin {
68d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID
69d3b33679SDmitry Kasatkin 	evm_hmac_attrs |= EVM_ATTR_FSUUID;
70d3b33679SDmitry Kasatkin #endif
71d3b33679SDmitry Kasatkin 	pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs);
72d3b33679SDmitry Kasatkin }
73d3b33679SDmitry Kasatkin 
7415647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry)
7515647eb3SDmitry Kasatkin {
76c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
7715647eb3SDmitry Kasatkin 	char **xattr;
7815647eb3SDmitry Kasatkin 	int error;
7915647eb3SDmitry Kasatkin 	int count = 0;
8015647eb3SDmitry Kasatkin 
815d6c3191SAndreas Gruenbacher 	if (!(inode->i_opflags & IOP_XATTR))
8215647eb3SDmitry Kasatkin 		return -EOPNOTSUPP;
8315647eb3SDmitry Kasatkin 
8415647eb3SDmitry Kasatkin 	for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
855d6c3191SAndreas Gruenbacher 		error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
8615647eb3SDmitry Kasatkin 		if (error < 0) {
8715647eb3SDmitry Kasatkin 			if (error == -ENODATA)
8815647eb3SDmitry Kasatkin 				continue;
8915647eb3SDmitry Kasatkin 			return error;
9015647eb3SDmitry Kasatkin 		}
9115647eb3SDmitry Kasatkin 		count++;
9215647eb3SDmitry Kasatkin 	}
9315647eb3SDmitry Kasatkin 
9415647eb3SDmitry Kasatkin 	return count;
9515647eb3SDmitry Kasatkin }
9615647eb3SDmitry Kasatkin 
9766dbc325SMimi Zohar /*
9866dbc325SMimi Zohar  * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
9966dbc325SMimi Zohar  *
10066dbc325SMimi Zohar  * Compute the HMAC on the dentry's protected set of extended attributes
1017102ebcdSMimi Zohar  * and compare it against the stored security.evm xattr.
1027102ebcdSMimi Zohar  *
1037102ebcdSMimi Zohar  * For performance:
1047102ebcdSMimi Zohar  * - use the previoulsy retrieved xattr value and length to calculate the
10566dbc325SMimi Zohar  *   HMAC.)
1067102ebcdSMimi Zohar  * - cache the verification result in the iint, when available.
10766dbc325SMimi Zohar  *
10866dbc325SMimi Zohar  * Returns integrity status
10966dbc325SMimi Zohar  */
11066dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry,
11166dbc325SMimi Zohar 					     const char *xattr_name,
11266dbc325SMimi Zohar 					     char *xattr_value,
11366dbc325SMimi Zohar 					     size_t xattr_value_len,
11466dbc325SMimi Zohar 					     struct integrity_iint_cache *iint)
11566dbc325SMimi Zohar {
11615647eb3SDmitry Kasatkin 	struct evm_ima_xattr_data *xattr_data = NULL;
11715647eb3SDmitry Kasatkin 	struct evm_ima_xattr_data calc;
118566be59aSMimi Zohar 	enum integrity_status evm_status = INTEGRITY_PASS;
11915647eb3SDmitry Kasatkin 	int rc, xattr_len;
12066dbc325SMimi Zohar 
1217102ebcdSMimi Zohar 	if (iint && iint->evm_status == INTEGRITY_PASS)
12224e0198eSDmitry Kasatkin 		return iint->evm_status;
12366dbc325SMimi Zohar 
1246d38ca01SDmitry Kasatkin 	/* if status is not PASS, try to check again - against -ENOMEM */
1256d38ca01SDmitry Kasatkin 
12615647eb3SDmitry Kasatkin 	/* first need to know the sig type */
12715647eb3SDmitry Kasatkin 	rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
12815647eb3SDmitry Kasatkin 				GFP_NOFS);
12915647eb3SDmitry Kasatkin 	if (rc <= 0) {
1301f100979SDmitry Kasatkin 		evm_status = INTEGRITY_FAIL;
1311f100979SDmitry Kasatkin 		if (rc == -ENODATA) {
13215647eb3SDmitry Kasatkin 			rc = evm_find_protected_xattrs(dentry);
13315647eb3SDmitry Kasatkin 			if (rc > 0)
13415647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOLABEL;
13515647eb3SDmitry Kasatkin 			else if (rc == 0)
13615647eb3SDmitry Kasatkin 				evm_status = INTEGRITY_NOXATTRS; /* new file */
1371f100979SDmitry Kasatkin 		} else if (rc == -EOPNOTSUPP) {
1381f100979SDmitry Kasatkin 			evm_status = INTEGRITY_UNKNOWN;
13915647eb3SDmitry Kasatkin 		}
140566be59aSMimi Zohar 		goto out;
141566be59aSMimi Zohar 	}
14266dbc325SMimi Zohar 
143b1aaab22SDmitry Kasatkin 	xattr_len = rc;
14415647eb3SDmitry Kasatkin 
14515647eb3SDmitry Kasatkin 	/* check value type */
14615647eb3SDmitry Kasatkin 	switch (xattr_data->type) {
14715647eb3SDmitry Kasatkin 	case EVM_XATTR_HMAC:
148b4bfec7fSSeth Forshee 		if (xattr_len != sizeof(struct evm_ima_xattr_data)) {
149b4bfec7fSSeth Forshee 			evm_status = INTEGRITY_FAIL;
150b4bfec7fSSeth Forshee 			goto out;
151b4bfec7fSSeth Forshee 		}
15215647eb3SDmitry Kasatkin 		rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
15315647eb3SDmitry Kasatkin 				   xattr_value_len, calc.digest);
15415647eb3SDmitry Kasatkin 		if (rc)
15515647eb3SDmitry Kasatkin 			break;
156613317bdSRyan Ware 		rc = crypto_memneq(xattr_data->digest, calc.digest,
15715647eb3SDmitry Kasatkin 			    sizeof(calc.digest));
15815647eb3SDmitry Kasatkin 		if (rc)
15915647eb3SDmitry Kasatkin 			rc = -EINVAL;
16015647eb3SDmitry Kasatkin 		break;
16115647eb3SDmitry Kasatkin 	case EVM_IMA_XATTR_DIGSIG:
16215647eb3SDmitry Kasatkin 		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
16315647eb3SDmitry Kasatkin 				xattr_value_len, calc.digest);
16415647eb3SDmitry Kasatkin 		if (rc)
16515647eb3SDmitry Kasatkin 			break;
16615647eb3SDmitry Kasatkin 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
167b1aaab22SDmitry Kasatkin 					(const char *)xattr_data, xattr_len,
16815647eb3SDmitry Kasatkin 					calc.digest, sizeof(calc.digest));
16915647eb3SDmitry Kasatkin 		if (!rc) {
170c2baec7fSDmitry Kasatkin 			/* Replace RSA with HMAC if not mounted readonly and
171c2baec7fSDmitry Kasatkin 			 * not immutable
172c2baec7fSDmitry Kasatkin 			 */
173c6f493d6SDavid Howells 			if (!IS_RDONLY(d_backing_inode(dentry)) &&
174c6f493d6SDavid Howells 			    !IS_IMMUTABLE(d_backing_inode(dentry)))
175c2baec7fSDmitry Kasatkin 				evm_update_evmxattr(dentry, xattr_name,
176c2baec7fSDmitry Kasatkin 						    xattr_value,
17715647eb3SDmitry Kasatkin 						    xattr_value_len);
17815647eb3SDmitry Kasatkin 		}
17915647eb3SDmitry Kasatkin 		break;
18015647eb3SDmitry Kasatkin 	default:
18115647eb3SDmitry Kasatkin 		rc = -EINVAL;
18215647eb3SDmitry Kasatkin 		break;
18315647eb3SDmitry Kasatkin 	}
18415647eb3SDmitry Kasatkin 
18515647eb3SDmitry Kasatkin 	if (rc)
18615647eb3SDmitry Kasatkin 		evm_status = (rc == -ENODATA) ?
18715647eb3SDmitry Kasatkin 				INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
1887102ebcdSMimi Zohar out:
1897102ebcdSMimi Zohar 	if (iint)
1907102ebcdSMimi Zohar 		iint->evm_status = evm_status;
19115647eb3SDmitry Kasatkin 	kfree(xattr_data);
1927102ebcdSMimi Zohar 	return evm_status;
19366dbc325SMimi Zohar }
19466dbc325SMimi Zohar 
19566dbc325SMimi Zohar static int evm_protected_xattr(const char *req_xattr_name)
19666dbc325SMimi Zohar {
19766dbc325SMimi Zohar 	char **xattrname;
19866dbc325SMimi Zohar 	int namelen;
19966dbc325SMimi Zohar 	int found = 0;
20066dbc325SMimi Zohar 
20166dbc325SMimi Zohar 	namelen = strlen(req_xattr_name);
20266dbc325SMimi Zohar 	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
20366dbc325SMimi Zohar 		if ((strlen(*xattrname) == namelen)
20466dbc325SMimi Zohar 		    && (strncmp(req_xattr_name, *xattrname, namelen) == 0)) {
20566dbc325SMimi Zohar 			found = 1;
20666dbc325SMimi Zohar 			break;
20766dbc325SMimi Zohar 		}
208cb723180SMimi Zohar 		if (strncmp(req_xattr_name,
209cb723180SMimi Zohar 			    *xattrname + XATTR_SECURITY_PREFIX_LEN,
210cb723180SMimi Zohar 			    strlen(req_xattr_name)) == 0) {
211cb723180SMimi Zohar 			found = 1;
212cb723180SMimi Zohar 			break;
213cb723180SMimi Zohar 		}
21466dbc325SMimi Zohar 	}
21566dbc325SMimi Zohar 	return found;
21666dbc325SMimi Zohar }
21766dbc325SMimi Zohar 
21866dbc325SMimi Zohar /**
21966dbc325SMimi Zohar  * evm_verifyxattr - verify the integrity of the requested xattr
22066dbc325SMimi Zohar  * @dentry: object of the verify xattr
22166dbc325SMimi Zohar  * @xattr_name: requested xattr
22266dbc325SMimi Zohar  * @xattr_value: requested xattr value
22366dbc325SMimi Zohar  * @xattr_value_len: requested xattr value length
22466dbc325SMimi Zohar  *
22566dbc325SMimi Zohar  * Calculate the HMAC for the given dentry and verify it against the stored
22666dbc325SMimi Zohar  * security.evm xattr. For performance, use the xattr value and length
22766dbc325SMimi Zohar  * previously retrieved to calculate the HMAC.
22866dbc325SMimi Zohar  *
22966dbc325SMimi Zohar  * Returns the xattr integrity status.
23066dbc325SMimi Zohar  *
23166dbc325SMimi Zohar  * This function requires the caller to lock the inode's i_mutex before it
23266dbc325SMimi Zohar  * is executed.
23366dbc325SMimi Zohar  */
23466dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry,
23566dbc325SMimi Zohar 				      const char *xattr_name,
2362960e6cbSDmitry Kasatkin 				      void *xattr_value, size_t xattr_value_len,
2372960e6cbSDmitry Kasatkin 				      struct integrity_iint_cache *iint)
23866dbc325SMimi Zohar {
23966dbc325SMimi Zohar 	if (!evm_initialized || !evm_protected_xattr(xattr_name))
24066dbc325SMimi Zohar 		return INTEGRITY_UNKNOWN;
24166dbc325SMimi Zohar 
2422960e6cbSDmitry Kasatkin 	if (!iint) {
243c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
24466dbc325SMimi Zohar 		if (!iint)
24566dbc325SMimi Zohar 			return INTEGRITY_UNKNOWN;
2462960e6cbSDmitry Kasatkin 	}
2472960e6cbSDmitry Kasatkin 	return evm_verify_hmac(dentry, xattr_name, xattr_value,
24866dbc325SMimi Zohar 				 xattr_value_len, iint);
24966dbc325SMimi Zohar }
25066dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr);
25166dbc325SMimi Zohar 
25266dbc325SMimi Zohar /*
2537102ebcdSMimi Zohar  * evm_verify_current_integrity - verify the dentry's metadata integrity
2547102ebcdSMimi Zohar  * @dentry: pointer to the affected dentry
2557102ebcdSMimi Zohar  *
2567102ebcdSMimi Zohar  * Verify and return the dentry's metadata integrity. The exceptions are
2577102ebcdSMimi Zohar  * before EVM is initialized or in 'fix' mode.
2587102ebcdSMimi Zohar  */
2597102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
2607102ebcdSMimi Zohar {
261c6f493d6SDavid Howells 	struct inode *inode = d_backing_inode(dentry);
2627102ebcdSMimi Zohar 
2637102ebcdSMimi Zohar 	if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode)
2647102ebcdSMimi Zohar 		return 0;
2657102ebcdSMimi Zohar 	return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
2667102ebcdSMimi Zohar }
2677102ebcdSMimi Zohar 
268a924ce0bSMimi Zohar /*
269a924ce0bSMimi Zohar  * evm_protect_xattr - protect the EVM extended attribute
270a924ce0bSMimi Zohar  *
271bf6d0f5dSMimi Zohar  * Prevent security.evm from being modified or removed without the
272bf6d0f5dSMimi Zohar  * necessary permissions or when the existing value is invalid.
273bf6d0f5dSMimi Zohar  *
274bf6d0f5dSMimi Zohar  * The posix xattr acls are 'system' prefixed, which normally would not
275bf6d0f5dSMimi Zohar  * affect security.evm.  An interesting side affect of writing posix xattr
276bf6d0f5dSMimi Zohar  * acls is their modifying of the i_mode, which is included in security.evm.
277bf6d0f5dSMimi Zohar  * For posix xattr acls only, permit security.evm, even if it currently
278bf6d0f5dSMimi Zohar  * doesn't exist, to be updated.
279a924ce0bSMimi Zohar  */
280a924ce0bSMimi Zohar static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
281a924ce0bSMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
282a924ce0bSMimi Zohar {
283a924ce0bSMimi Zohar 	enum integrity_status evm_status;
284a924ce0bSMimi Zohar 
285a924ce0bSMimi Zohar 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
286a924ce0bSMimi Zohar 		if (!capable(CAP_SYS_ADMIN))
287a924ce0bSMimi Zohar 			return -EPERM;
288bf6d0f5dSMimi Zohar 	} else if (!evm_protected_xattr(xattr_name)) {
289bf6d0f5dSMimi Zohar 		if (!posix_xattr_acl(xattr_name))
290a924ce0bSMimi Zohar 			return 0;
291bf6d0f5dSMimi Zohar 		evm_status = evm_verify_current_integrity(dentry);
292bf6d0f5dSMimi Zohar 		if ((evm_status == INTEGRITY_PASS) ||
293566be59aSMimi Zohar 		    (evm_status == INTEGRITY_NOXATTRS))
294bf6d0f5dSMimi Zohar 			return 0;
2959b97b6cdSMimi Zohar 		goto out;
296bf6d0f5dSMimi Zohar 	}
297a924ce0bSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
2983dcbad52SDmitry Kasatkin 	if (evm_status == INTEGRITY_NOXATTRS) {
2993dcbad52SDmitry Kasatkin 		struct integrity_iint_cache *iint;
3003dcbad52SDmitry Kasatkin 
301c6f493d6SDavid Howells 		iint = integrity_iint_find(d_backing_inode(dentry));
3023dcbad52SDmitry Kasatkin 		if (iint && (iint->flags & IMA_NEW_FILE))
3033dcbad52SDmitry Kasatkin 			return 0;
3045101a185SMimi Zohar 
3055101a185SMimi Zohar 		/* exception for pseudo filesystems */
306fc64005cSAl Viro 		if (dentry->d_sb->s_magic == TMPFS_MAGIC
307fc64005cSAl Viro 		    || dentry->d_sb->s_magic == SYSFS_MAGIC)
3085101a185SMimi Zohar 			return 0;
3095101a185SMimi Zohar 
3105101a185SMimi Zohar 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
3115101a185SMimi Zohar 				    dentry->d_inode, dentry->d_name.name,
3125101a185SMimi Zohar 				    "update_metadata",
3135101a185SMimi Zohar 				    integrity_status_msg[evm_status],
3145101a185SMimi Zohar 				    -EPERM, 0);
3153dcbad52SDmitry Kasatkin 	}
3169b97b6cdSMimi Zohar out:
3179b97b6cdSMimi Zohar 	if (evm_status != INTEGRITY_PASS)
318c6f493d6SDavid Howells 		integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
3199b97b6cdSMimi Zohar 				    dentry->d_name.name, "appraise_metadata",
3209b97b6cdSMimi Zohar 				    integrity_status_msg[evm_status],
3219b97b6cdSMimi Zohar 				    -EPERM, 0);
322a924ce0bSMimi Zohar 	return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
323a924ce0bSMimi Zohar }
324a924ce0bSMimi Zohar 
32566dbc325SMimi Zohar /**
32666dbc325SMimi Zohar  * evm_inode_setxattr - protect the EVM extended attribute
32766dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
32866dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
32966dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
33066dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
33166dbc325SMimi Zohar  *
3322fb1c9a4SMimi Zohar  * Before allowing the 'security.evm' protected xattr to be updated,
3332fb1c9a4SMimi Zohar  * verify the existing value is valid.  As only the kernel should have
3342fb1c9a4SMimi Zohar  * access to the EVM encrypted key needed to calculate the HMAC, prevent
3352fb1c9a4SMimi Zohar  * userspace from writing HMAC value.  Writing 'security.evm' requires
3362fb1c9a4SMimi Zohar  * requires CAP_SYS_ADMIN privileges.
33766dbc325SMimi Zohar  */
33866dbc325SMimi Zohar int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
33966dbc325SMimi Zohar 		       const void *xattr_value, size_t xattr_value_len)
34066dbc325SMimi Zohar {
3412fb1c9a4SMimi Zohar 	const struct evm_ima_xattr_data *xattr_data = xattr_value;
3422fb1c9a4SMimi Zohar 
3433b1deef6SDmitry Kasatkin 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
3443b1deef6SDmitry Kasatkin 		if (!xattr_value_len)
3453b1deef6SDmitry Kasatkin 			return -EINVAL;
3463b1deef6SDmitry Kasatkin 		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG)
3472fb1c9a4SMimi Zohar 			return -EPERM;
3483b1deef6SDmitry Kasatkin 	}
349a924ce0bSMimi Zohar 	return evm_protect_xattr(dentry, xattr_name, xattr_value,
35066dbc325SMimi Zohar 				 xattr_value_len);
35166dbc325SMimi Zohar }
35266dbc325SMimi Zohar 
35366dbc325SMimi Zohar /**
35466dbc325SMimi Zohar  * evm_inode_removexattr - protect the EVM extended attribute
35566dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
35666dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
35766dbc325SMimi Zohar  *
3587102ebcdSMimi Zohar  * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
3597102ebcdSMimi Zohar  * the current value is valid.
36066dbc325SMimi Zohar  */
36166dbc325SMimi Zohar int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)
36266dbc325SMimi Zohar {
363a924ce0bSMimi Zohar 	return evm_protect_xattr(dentry, xattr_name, NULL, 0);
36466dbc325SMimi Zohar }
36566dbc325SMimi Zohar 
366523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode)
367523b74b1SDmitry Kasatkin {
368523b74b1SDmitry Kasatkin 	struct integrity_iint_cache *iint;
369523b74b1SDmitry Kasatkin 
370523b74b1SDmitry Kasatkin 	iint = integrity_iint_find(inode);
371523b74b1SDmitry Kasatkin 	if (iint)
372523b74b1SDmitry Kasatkin 		iint->evm_status = INTEGRITY_UNKNOWN;
373523b74b1SDmitry Kasatkin }
374523b74b1SDmitry Kasatkin 
37566dbc325SMimi Zohar /**
37666dbc325SMimi Zohar  * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
37766dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
37866dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
37966dbc325SMimi Zohar  * @xattr_value: pointer to the new extended attribute value
38066dbc325SMimi Zohar  * @xattr_value_len: pointer to the new extended attribute value length
38166dbc325SMimi Zohar  *
38266dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect the change.
38366dbc325SMimi Zohar  *
38466dbc325SMimi Zohar  * No need to take the i_mutex lock here, as this function is called from
38566dbc325SMimi Zohar  * __vfs_setxattr_noperm().  The caller of which has taken the inode's
38666dbc325SMimi Zohar  * i_mutex lock.
38766dbc325SMimi Zohar  */
38866dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
38966dbc325SMimi Zohar 			     const void *xattr_value, size_t xattr_value_len)
39066dbc325SMimi Zohar {
391bf6d0f5dSMimi Zohar 	if (!evm_initialized || (!evm_protected_xattr(xattr_name)
392bf6d0f5dSMimi Zohar 				 && !posix_xattr_acl(xattr_name)))
39366dbc325SMimi Zohar 		return;
39466dbc325SMimi Zohar 
395523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
396523b74b1SDmitry Kasatkin 
39766dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
39866dbc325SMimi Zohar }
39966dbc325SMimi Zohar 
40066dbc325SMimi Zohar /**
40166dbc325SMimi Zohar  * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
40266dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
40366dbc325SMimi Zohar  * @xattr_name: pointer to the affected extended attribute name
40466dbc325SMimi Zohar  *
40566dbc325SMimi Zohar  * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
4067c51bb00SDmitry Kasatkin  *
4077c51bb00SDmitry Kasatkin  * No need to take the i_mutex lock here, as this function is called from
4087c51bb00SDmitry Kasatkin  * vfs_removexattr() which takes the i_mutex.
40966dbc325SMimi Zohar  */
41066dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
41166dbc325SMimi Zohar {
41266dbc325SMimi Zohar 	if (!evm_initialized || !evm_protected_xattr(xattr_name))
41366dbc325SMimi Zohar 		return;
41466dbc325SMimi Zohar 
415523b74b1SDmitry Kasatkin 	evm_reset_status(dentry->d_inode);
416523b74b1SDmitry Kasatkin 
41766dbc325SMimi Zohar 	evm_update_evmxattr(dentry, xattr_name, NULL, 0);
41866dbc325SMimi Zohar }
41966dbc325SMimi Zohar 
42066dbc325SMimi Zohar /**
421817b54aaSMimi Zohar  * evm_inode_setattr - prevent updating an invalid EVM extended attribute
422817b54aaSMimi Zohar  * @dentry: pointer to the affected dentry
423817b54aaSMimi Zohar  */
424817b54aaSMimi Zohar int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
425817b54aaSMimi Zohar {
426817b54aaSMimi Zohar 	unsigned int ia_valid = attr->ia_valid;
427817b54aaSMimi Zohar 	enum integrity_status evm_status;
428817b54aaSMimi Zohar 
429a924ce0bSMimi Zohar 	if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
430817b54aaSMimi Zohar 		return 0;
431817b54aaSMimi Zohar 	evm_status = evm_verify_current_integrity(dentry);
432566be59aSMimi Zohar 	if ((evm_status == INTEGRITY_PASS) ||
433566be59aSMimi Zohar 	    (evm_status == INTEGRITY_NOXATTRS))
434566be59aSMimi Zohar 		return 0;
435c6f493d6SDavid Howells 	integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
4369b97b6cdSMimi Zohar 			    dentry->d_name.name, "appraise_metadata",
4379b97b6cdSMimi Zohar 			    integrity_status_msg[evm_status], -EPERM, 0);
438566be59aSMimi Zohar 	return -EPERM;
439817b54aaSMimi Zohar }
440817b54aaSMimi Zohar 
441817b54aaSMimi Zohar /**
44266dbc325SMimi Zohar  * evm_inode_post_setattr - update 'security.evm' after modifying metadata
44366dbc325SMimi Zohar  * @dentry: pointer to the affected dentry
44466dbc325SMimi Zohar  * @ia_valid: for the UID and GID status
44566dbc325SMimi Zohar  *
44666dbc325SMimi Zohar  * For now, update the HMAC stored in 'security.evm' to reflect UID/GID
44766dbc325SMimi Zohar  * changes.
44866dbc325SMimi Zohar  *
44966dbc325SMimi Zohar  * This function is called from notify_change(), which expects the caller
45066dbc325SMimi Zohar  * to lock the inode's i_mutex.
45166dbc325SMimi Zohar  */
45266dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
45366dbc325SMimi Zohar {
45466dbc325SMimi Zohar 	if (!evm_initialized)
45566dbc325SMimi Zohar 		return;
45666dbc325SMimi Zohar 
45766dbc325SMimi Zohar 	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
45866dbc325SMimi Zohar 		evm_update_evmxattr(dentry, NULL, NULL, 0);
45966dbc325SMimi Zohar }
46066dbc325SMimi Zohar 
461cb723180SMimi Zohar /*
462cb723180SMimi Zohar  * evm_inode_init_security - initializes security.evm
463cb723180SMimi Zohar  */
464cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode,
465cb723180SMimi Zohar 				 const struct xattr *lsm_xattr,
466cb723180SMimi Zohar 				 struct xattr *evm_xattr)
467cb723180SMimi Zohar {
468cb723180SMimi Zohar 	struct evm_ima_xattr_data *xattr_data;
469cb723180SMimi Zohar 	int rc;
470cb723180SMimi Zohar 
471cb723180SMimi Zohar 	if (!evm_initialized || !evm_protected_xattr(lsm_xattr->name))
4725a4730baSMimi Zohar 		return 0;
473cb723180SMimi Zohar 
474cb723180SMimi Zohar 	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
475cb723180SMimi Zohar 	if (!xattr_data)
476cb723180SMimi Zohar 		return -ENOMEM;
477cb723180SMimi Zohar 
478cb723180SMimi Zohar 	xattr_data->type = EVM_XATTR_HMAC;
479cb723180SMimi Zohar 	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
480cb723180SMimi Zohar 	if (rc < 0)
481cb723180SMimi Zohar 		goto out;
482cb723180SMimi Zohar 
483cb723180SMimi Zohar 	evm_xattr->value = xattr_data;
484cb723180SMimi Zohar 	evm_xattr->value_len = sizeof(*xattr_data);
4859548906bSTetsuo Handa 	evm_xattr->name = XATTR_EVM_SUFFIX;
486cb723180SMimi Zohar 	return 0;
487cb723180SMimi Zohar out:
488cb723180SMimi Zohar 	kfree(xattr_data);
489cb723180SMimi Zohar 	return rc;
490cb723180SMimi Zohar }
491cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security);
492cb723180SMimi Zohar 
4932ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509
4942ce523ebSDmitry Kasatkin void __init evm_load_x509(void)
4952ce523ebSDmitry Kasatkin {
49626ddabfeSDmitry Kasatkin 	int rc;
49726ddabfeSDmitry Kasatkin 
49826ddabfeSDmitry Kasatkin 	rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH);
49926ddabfeSDmitry Kasatkin 	if (!rc)
50026ddabfeSDmitry Kasatkin 		evm_initialized |= EVM_INIT_X509;
5012ce523ebSDmitry Kasatkin }
5022ce523ebSDmitry Kasatkin #endif
5032ce523ebSDmitry Kasatkin 
50466dbc325SMimi Zohar static int __init init_evm(void)
50566dbc325SMimi Zohar {
50666dbc325SMimi Zohar 	int error;
50766dbc325SMimi Zohar 
508d3b33679SDmitry Kasatkin 	evm_init_config();
509d3b33679SDmitry Kasatkin 
510f4dc3778SDmitry Kasatkin 	error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
511f4dc3778SDmitry Kasatkin 	if (error)
512f4dc3778SDmitry Kasatkin 		return error;
513f4dc3778SDmitry Kasatkin 
51466dbc325SMimi Zohar 	error = evm_init_secfs();
51566dbc325SMimi Zohar 	if (error < 0) {
51620ee451fSJoe Perches 		pr_info("Error registering secfs\n");
517f4dc3778SDmitry Kasatkin 		return error;
51866dbc325SMimi Zohar 	}
51915647eb3SDmitry Kasatkin 
52015647eb3SDmitry Kasatkin 	return 0;
52166dbc325SMimi Zohar }
52266dbc325SMimi Zohar 
52366dbc325SMimi Zohar /*
52466dbc325SMimi Zohar  * evm_display_config - list the EVM protected security extended attributes
52566dbc325SMimi Zohar  */
52666dbc325SMimi Zohar static int __init evm_display_config(void)
52766dbc325SMimi Zohar {
52866dbc325SMimi Zohar 	char **xattrname;
52966dbc325SMimi Zohar 
53066dbc325SMimi Zohar 	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
53120ee451fSJoe Perches 		pr_info("%s\n", *xattrname);
53266dbc325SMimi Zohar 	return 0;
53366dbc325SMimi Zohar }
53466dbc325SMimi Zohar 
53566dbc325SMimi Zohar pure_initcall(evm_display_config);
53666dbc325SMimi Zohar late_initcall(init_evm);
53766dbc325SMimi Zohar 
53866dbc325SMimi Zohar MODULE_DESCRIPTION("Extended Verification Module");
53966dbc325SMimi Zohar MODULE_LICENSE("GPL");
540