diff --git a/include/linux/evm.h b/include/linux/evm.h
index 8302bc29bb35..e5b7bcb152b9 100644
--- a/include/linux/evm.h
+++ b/include/linux/evm.h
@@ -35,6 +35,7 @@ extern void evm_inode_post_removexattr(struct dentry *dentry,
extern int evm_inode_init_security(struct inode *inode,
const struct xattr *xattr_array,
struct xattr *evm);
+extern bool evm_status_revalidate(const char *xattr_name);
#ifdef CONFIG_FS_POSIX_ACL
extern int posix_xattr_acl(const char *xattrname);
#else
@@ -104,5 +105,10 @@ static inline int evm_inode_init_security(struct inode *inode,
return 0;
}
+static inline bool evm_status_revalidate(const char *xattr_name)
+{
+ return false;
+}
+
#endif /* CONFIG_EVM */
#endif /* LINUX_EVM_H */diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 7ac5204c8d1f..998818283fda 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -425,6 +425,30 @@ static void evm_reset_status(struct inode *inode)
iint->evm_status = INTEGRITY_UNKNOWN;
}
+/**
+ * evm_status_revalidate - report whether EVM status re-validation is necessary
+ * @xattr_name: pointer to the affected extended attribute name
+ *
+ * Report whether callers of evm_verifyxattr() should re-validate the
+ * EVM status.
+ *
+ * Return true if re-validation is necessary, false otherwise.
+ */
+bool evm_status_revalidate(const char *xattr_name)
+{
+ if (!evm_key_loaded())
+ return false;
+
+ /* evm_inode_post_setattr() passes NULL */
+ if (!xattr_name)
+ return true;
+
+ if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name))
+ return false;
+
+ return true;
+}
+
/**
* evm_inode_post_setxattr - update 'security.evm' to reflect the changes
* @dentry: pointer to the affected dentry@@ -441,8 +465,7 @@ static void evm_reset_status(struct inode *inode)
void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len)
{
- if (!evm_key_loaded() || (!evm_protected_xattr(xattr_name)
- && !posix_xattr_acl(xattr_name)))
+ if (!evm_status_revalidate(xattr_name))
return;
evm_reset_status(dentry->d_inode);@@ -462,7 +485,7 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
*/
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
{
- if (!evm_key_loaded() || !evm_protected_xattr(xattr_name))
+ if (!evm_status_revalidate(xattr_name))
return;
evm_reset_status(dentry->d_inode);@@ -513,9 +536,11 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
*/
void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
{
- if (!evm_key_loaded())
+ if (!evm_status_revalidate(NULL))
return;
+ evm_reset_status(dentry->d_inode);
+
if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
evm_update_evmxattr(dentry, NULL, NULL, 0);
}diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 1f029e4c8d7f..d4b8db1acadd 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -586,13 +586,15 @@ void ima_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len)
{
const struct evm_ima_xattr_data *xvalue = xattr_value;
+ int digsig = 0;
int result;
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
xattr_value_len);
if (result == 1)
- ima_reset_appraise_flags(d_backing_inode(dentry),
- xvalue->type == EVM_IMA_XATTR_DIGSIG);
+ digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
+ if (result == 1 || evm_status_revalidate(xattr_name))
+ ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
}
int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)@@ -611,6 +613,6 @@ void ima_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
int result;
result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
- if (result == 1)
+ if (result == 1 || evm_status_revalidate(xattr_name))
ima_reset_appraise_flags(d_backing_inode(dentry), 0);
}
--
2.26.2