cifs: Do not leak EDEADLK to dgetents64 for STATUS_USER_SESSION_DELETED
authorRonnie Sahlberg <lsahlber@redhat.com>
Wed, 25 Aug 2021 11:16:56 +0000 (21:16 +1000)
committerSteve French <stfrench@microsoft.com>
Wed, 25 Aug 2021 21:08:38 +0000 (16:08 -0500)
RHBZ: 1994393

If we hit a STATUS_USER_SESSION_DELETED for the Create part in the
Create/QueryDirectory compound that starts a directory scan
we will leak EDEADLK back to userspace and surprise glibc and the application.

Pick this up initiate_cifs_search() and retry a small number of tries before we
return an error to userspace.

Cc: stable@vger.kernel.org
Reported-by: Xiaoli Feng <xifeng@redhat.com>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/readdir.c

index bfee176..54d77c9 100644 (file)
@@ -369,7 +369,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
  */
 
 static int
-initiate_cifs_search(const unsigned int xid, struct file *file,
+_initiate_cifs_search(const unsigned int xid, struct file *file,
                     const char *full_path)
 {
        __u16 search_flags;
@@ -451,6 +451,27 @@ error_exit:
        return rc;
 }
 
+static int
+initiate_cifs_search(const unsigned int xid, struct file *file,
+                    const char *full_path)
+{
+       int rc, retry_count = 0;
+
+       do {
+               rc = _initiate_cifs_search(xid, file, full_path);
+               /*
+                * If we don't have enough credits to start reading the
+                * directory just try again after short wait.
+                */
+               if (rc != -EDEADLK)
+                       break;
+
+               usleep_range(512, 2048);
+       } while (retry_count++ < 5);
+
+       return rc;
+}
+
 /* return length of unicode string in bytes */
 static int cifs_unicode_bytelen(const char *str)
 {