extern int evm_inode_init_security(struct inode *inode,
                                   const struct xattr *xattr_array,
                                   struct xattr *evm);
+extern bool evm_revalidate_status(const char *xattr_name);
 #ifdef CONFIG_FS_POSIX_ACL
 extern int posix_xattr_acl(const char *xattrname);
 #else
        return 0;
 }
 
+static inline bool evm_revalidate_status(const char *xattr_name)
+{
+       return false;
+}
+
 #endif /* CONFIG_EVM */
 #endif /* LINUX_EVM_H */
 
                iint->evm_status = INTEGRITY_UNKNOWN;
 }
 
+/**
+ * evm_revalidate_status - 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_revalidate_status(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) &&
+           strcmp(xattr_name, XATTR_NAME_EVM))
+               return false;
+
+       return true;
+}
+
 /**
  * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
  * @dentry: pointer to the affected dentry
 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_revalidate_status(xattr_name))
                return;
 
        evm_reset_status(dentry->d_inode);
 
+       if (!strcmp(xattr_name, XATTR_NAME_EVM))
+               return;
+
        evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
 }
 
  */
 void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
 {
-       if (!evm_key_loaded() || !evm_protected_xattr(xattr_name))
+       if (!evm_revalidate_status(xattr_name))
                return;
 
        evm_reset_status(dentry->d_inode);
 
+       if (!strcmp(xattr_name, XATTR_NAME_EVM))
+               return;
+
        evm_update_evmxattr(dentry, xattr_name, NULL, 0);
 }
 
  */
 void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
 {
-       if (!evm_key_loaded())
+       if (!evm_revalidate_status(NULL))
                return;
 
+       evm_reset_status(dentry->d_inode);
+
        if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
                evm_update_evmxattr(dentry, NULL, NULL, 0);
 }
 
                       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,
        if (result == 1) {
                if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
                        return -EINVAL;
-               ima_reset_appraise_flags(d_backing_inode(dentry),
-                       xvalue->type == EVM_IMA_XATTR_DIGSIG);
-               result = 0;
+               digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
+       }
+       if (result == 1 || evm_revalidate_status(xattr_name)) {
+               ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
+               if (result == 1)
+                       result = 0;
        }
        return result;
 }
        int result;
 
        result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
-       if (result == 1) {
+       if (result == 1 || evm_revalidate_status(xattr_name)) {
                ima_reset_appraise_flags(d_backing_inode(dentry), 0);
-               result = 0;
+               if (result == 1)
+                       result = 0;
        }
        return result;
 }