return 0;
 }
 
+static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
+
+/*
+ * Try reloading inode security labels that have been marked as invalid.  The
+ * @may_sleep parameter indicates when sleeping and thus reloading labels is
+ * allowed; when set to false, returns ERR_PTR(-ECHILD) when the label is
+ * invalid.  The @opt_dentry parameter should be set to a dentry of the inode;
+ * when no dentry is available, set it to NULL instead.
+ */
+static int __inode_security_revalidate(struct inode *inode,
+                                      struct dentry *opt_dentry,
+                                      bool may_sleep)
+{
+       struct inode_security_struct *isec = inode->i_security;
+
+       might_sleep_if(may_sleep);
+
+       if (isec->initialized == LABEL_INVALID) {
+               if (!may_sleep)
+                       return -ECHILD;
+
+               /*
+                * Try reloading the inode security label.  This will fail if
+                * @opt_dentry is NULL and no dentry for this inode can be
+                * found; in that case, continue using the old label.
+                */
+               inode_doinit_with_dentry(inode, opt_dentry);
+       }
+       return 0;
+}
+
+static void inode_security_revalidate(struct inode *inode)
+{
+       __inode_security_revalidate(inode, NULL, true);
+}
+
+static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
+{
+       return inode->i_security;
+}
+
+static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
+{
+       int error;
+
+       error = __inode_security_revalidate(inode, NULL, !rcu);
+       if (error)
+               return ERR_PTR(error);
+       return inode->i_security;
+}
+
 /*
  * Get the security label of an inode.
  */
 static struct inode_security_struct *inode_security(struct inode *inode)
 {
+       __inode_security_revalidate(inode, NULL, true);
        return inode->i_security;
 }
 
 {
        struct inode *inode = d_backing_inode(dentry);
 
+       __inode_security_revalidate(inode, dentry, true);
        return inode->i_security;
 }
 
        "uses native labeling",
 };
 
-static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
-
 static inline int inode_doinit(struct inode *inode)
 {
        return inode_doinit_with_dentry(inode, NULL);
 
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
+       __inode_security_revalidate(inode, dentry, true);
        return inode_has_perm(cred, inode, av, &ad);
 }
 
 
        ad.type = LSM_AUDIT_DATA_PATH;
        ad.u.path = *path;
+       __inode_security_revalidate(inode, path->dentry, true);
        return inode_has_perm(cred, inode, av, &ad);
 }
 
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
        sid = cred_sid(cred);
-       isec = inode_security(inode);
+       isec = inode_security_rcu(inode, rcu);
+       if (IS_ERR(isec))
+               return PTR_ERR(isec);
 
        return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
                                  rcu ? MAY_NOT_BLOCK : 0);
        perms = file_mask_to_av(inode->i_mode, mask);
 
        sid = cred_sid(cred);
-       isec = inode_security(inode);
+       isec = inode_security_rcu(inode, flags & MAY_NOT_BLOCK);
+       if (IS_ERR(isec))
+               return PTR_ERR(isec);
 
        rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
        audited = avc_audit_required(perms, &avd, rc,
                /* No change since file_open check. */
                return 0;
 
+       inode_security_revalidate(inode);
        return selinux_revalidate_file_permission(file, mask);
 }
 
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
+       inode_security_revalidate(file_inode(file));
        return file_path_has_perm(cred, file, open_file_to_av(file));
 }
 
                                      int type, int protocol, int kern)
 {
        const struct task_security_struct *tsec = current_security();
-       struct inode_security_struct *isec = inode_security(SOCK_INODE(sock));
+       struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
        struct sk_security_struct *sksec;
        int err = 0;
 
        if (err)
                return err;
 
-       newisec = inode_security(SOCK_INODE(newsock));
+       newisec = inode_security_novalidate(SOCK_INODE(newsock));
 
-       isec = inode_security(SOCK_INODE(sock));
+       isec = inode_security_novalidate(SOCK_INODE(sock));
        newisec->sclass = isec->sclass;
        newisec->sid = isec->sid;
        newisec->initialized = LABEL_INITIALIZED;
 
 static void selinux_sock_graft(struct sock *sk, struct socket *parent)
 {
-       struct inode_security_struct *isec = inode_security(SOCK_INODE(parent));
+       struct inode_security_struct *isec =
+               inode_security_novalidate(SOCK_INODE(parent));
        struct sk_security_struct *sksec = sk->sk_security;
 
        if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||