lightly updated to add short sleep before retry On Wed, Aug 25, 2021 at 6:17 AM Ronnie Sahlberg <lsahlber@xxxxxxxxxx> wrote: > > 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@xxxxxxxxxxxxxxx > Reported-by: Xiaoli Feng <xifeng@xxxxxxxxxx> > Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> > --- > fs/cifs/readdir.c | 19 ++++++++++++++++++- > 1 file changed, 18 insertions(+), 1 deletion(-) > > diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c > index bfee176b901d..4518e3ca64df 100644 > --- a/fs/cifs/readdir.c > +++ b/fs/cifs/readdir.c > @@ -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,23 @@ initiate_cifs_search(const unsigned int xid, struct file *file, > 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); > + /* > + * We don't have enough credits to start reading the > + * directory so just try again. > + */ > + } while (rc == -EDEADLK && retry_count++ < 5); > + > + return rc; > +} > + > /* return length of unicode string in bytes */ > static int cifs_unicode_bytelen(const char *str) > { > -- > 2.30.2 > -- Thanks, Steve
From 57cea50fa5a30068752a8155e1c7230c8c585493 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Date: Wed, 25 Aug 2021 21:16:56 +1000 Subject: [PATCH] cifs: Do not leak EDEADLK to dgetents64 for STATUS_USER_SESSION_DELETED 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@xxxxxxxxxxxxxxx Reported-by: Xiaoli Feng <xifeng@xxxxxxxxxx> Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/readdir.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index bfee176b901d..54d77c99e21c 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -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 @@ initiate_cifs_search(const unsigned int xid, struct file *file, 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) { -- 2.30.2