]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ksmbd: retry iterate_dir in smb2_query_dir
authorHobin Woo <hobin.woo@samsung.com>
Thu, 5 Dec 2024 02:31:19 +0000 (11:31 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jan 2025 12:30:04 +0000 (13:30 +0100)
[ Upstream commit 2b904d61a97e8ba79e3bc216ba290fd7e1d85028 ]

Some file systems do not ensure that the single call of iterate_dir
reaches the end of the directory. For example, FUSE fetches entries from
a daemon using 4KB buffer and stops fetching if entries exceed the
buffer. And then an actor of caller, KSMBD, is used to fill the entries
from the buffer.
Thus, pattern searching on FUSE, files located after the 4KB could not
be found and STATUS_NO_SUCH_FILE was returned.

Signed-off-by: Hobin Woo <hobin.woo@samsung.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Tested-by: Yoonho Shin <yoonho.shin@samsung.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/server/smb2pdu.c
fs/smb/server/vfs.h

index 96d441ca511d46a77034dff6bbcf225e964ed7d6..71478a590e8348521ecd5888d98483c3adca41b0 100644 (file)
@@ -3988,6 +3988,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
        /* dot and dotdot entries are already reserved */
        if (!strcmp(".", name) || !strcmp("..", name))
                return true;
+       d_info->num_scan++;
        if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
                return true;
        if (!match_pattern(name, namlen, priv->search_pattern))
@@ -4148,8 +4149,17 @@ int smb2_query_dir(struct ksmbd_work *work)
        query_dir_private.info_level            = req->FileInformationClass;
        dir_fp->readdir_data.private            = &query_dir_private;
        set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
-
+again:
+       d_info.num_scan = 0;
        rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
+       /*
+        * num_entry can be 0 if the directory iteration stops before reaching
+        * the end of the directory and no file is matched with the search
+        * pattern.
+        */
+       if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
+           d_info.out_buf_len > 0)
+               goto again;
        /*
         * req->OutputBufferLength is too small to contain even one entry.
         * In this case, it immediately returns OutputBufferLength 0 to client.
index e761dde2443e2d02bb53ef6034d113360bc6b9ed..cc47e71c4de13ae9c2b98aa6d0d569e7b5db8b31 100644 (file)
@@ -43,6 +43,7 @@ struct ksmbd_dir_info {
        char            *rptr;
        int             name_len;
        int             out_buf_len;
+       int             num_scan;
        int             num_entry;
        int             data_count;
        int             last_entry_offset;