 fs/stat.c                  | 2 +-
 include/linux/security.h   | 9 ++++++---
 security/apparmor/lsm.c    | 4 +++-
 security/capability.c      | 2 +-
 security/security.c        | 4 ++--
 security/selinux/hooks.c   | 5 ++++-
 security/smack/smack_lsm.c | 7 ++++++-
 security/tomoyo/tomoyo.c   | 4 +++-
 8 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/fs/stat.c b/fs/stat.c
index d0ea7ef75e26..c3ed76c95b67 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -42,7 +42,7 @@ int vfs_getattr(struct path *path, struct kstat *stat)
 	struct inode *inode = path->dentry->d_inode;
 	int retval;
 
-	retval = security_inode_getattr(path->mnt, path->dentry);
+	retval = security_inode_getattr(path->mnt, path->dentry, 0);
 	if (retval)
 		return retval;
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 9d37e2b9d3ec..ba0480b86351 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -505,7 +505,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	Check permission before obtaining file attributes.
  *	@mnt is the vfsmount where the dentry was looked up
  *	@dentry contains the dentry structure for the file.
+ *	@mask contains MAY_NOT_BLOCK is set if this is a lockless lookup
  *	Return 0 if permission is granted.
+ *	Return -ECHILD if you cannot do it locklessly and MAY_NOT_BLOCK is set
  * @inode_setxattr:
  *	Check permission before setting the extended attributes
  *	@value identified by @name for @dentry.
@@ -1511,7 +1513,7 @@ struct security_operations {
 	int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
 	int (*inode_permission) (struct inode *inode, int mask);
 	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
-	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
+	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry, int mask);
 	int (*inode_setxattr) (struct dentry *dentry, const char *name,
 			       const void *value, size_t size, int flags);
 	void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
@@ -1787,7 +1789,7 @@ int security_inode_readlink(struct dentry *dentry);
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
 int security_inode_permission(struct inode *inode, int mask);
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
-int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
+int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask);
 int security_inode_setxattr(struct dentry *dentry, const char *name,
 			    const void *value, size_t size, int flags);
 void security_inode_post_setxattr(struct dentry *dentry, const char *name,
@@ -2178,7 +2180,8 @@ static inline int security_inode_setattr(struct dentry *dentry,
 }
 
 static inline int security_inode_getattr(struct vfsmount *mnt,
-					  struct dentry *dentry)
+					  struct dentry *dentry,
+					  int mask)
 {
 	return 0;
 }
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index fb99e18123b4..af07024510f4 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -364,10 +364,12 @@ static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
 	return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond);
 }
 
-static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask)
 {
 	if (!mediated_filesystem(dentry->d_inode))
 		return 0;
+	if (mask & MAY_NOT_BLOCK)
+		return -ECHILD;
 
 	return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry,
 				      AA_MAY_META_READ);
diff --git a/security/capability.c b/security/capability.c
index dbeb9bc27b24..2fa80ae08a42 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -202,7 +202,7 @@ static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 	return 0;
 }
 
-static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask)
 {
 	return 0;
 }
diff --git a/security/security.c b/security/security.c
index 4dc31f4f2700..b2423fa64983 100644
--- a/security/security.c
+++ b/security/security.c
@@ -567,11 +567,11 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 }
 EXPORT_SYMBOL_GPL(security_inode_setattr);
 
-int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask)
 {
 	if (unlikely(IS_PRIVATE(dentry->d_inode)))
 		return 0;
-	return security_ops->inode_getattr(mnt, dentry);
+	return security_ops->inode_getattr(mnt, dentry, mask);
 }
 
 int security_inode_setxattr(struct dentry *dentry, const char *name,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a5091ec06aa6..0dafce8524fd 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2785,11 +2785,14 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 	return dentry_has_perm(cred, dentry, av);
 }
 
-static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask)
 {
 	const struct cred *cred = current_cred();
 	struct path path;
 
+	if (mask & MAY_NOT_BLOCK)
+		return -ECHILD;
+
 	path.dentry = dentry;
 	path.mnt = mnt;
 
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 8825375cc031..3bc34b02434e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -808,10 +808,15 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
  *
  * Returns 0 if access is permitted, an error code otherwise
  */
-static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask)
 {
 	struct smk_audit_info ad;
 	struct path path;
+	int no_block = mask & MAY_NOT_BLOCK;
+
+	/* May be droppable after audit */
+	if (no_block)
+		return -ECHILD;
 
 	path.dentry = dentry;
 	path.mnt = mnt;
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index f0b756e27fed..a0c1b4fff196 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -144,9 +144,11 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
  *
  * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, int mask)
 {
 	struct path path = { mnt, dentry };
+	if (mask & MAY_NOT_BLOCK)
+		return -ECHILD;
 	return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL);
 }
 
