diff mbox series

[3/3] smb: client: handle max length for SMB symlinks

Message ID 20241118153516.48676-3-pc@manguebit.com (mailing list archive)
State New
Headers show
Series [1/3] smb: client: improve compound padding in encryption | expand

Commit Message

Paulo Alcantara Nov. 18, 2024, 3:35 p.m. UTC
We can't use PATH_MAX for SMB symlinks because

  (1) Windows Server will fail FSCTL_SET_REPARSE_POINT with
      STATUS_IO_REPARSE_DATA_INVALID when input buffer is larger than
      16K, as specified in MS-FSA 2.1.5.10.37.

  (2) The client won't be able to parse large SMB responses that
      includes SMB symlink path within SMB2_CREATE or SMB2_IOCTL
      responses.

Fix this by defining a maximum length value (4060) for SMB symlinks
that both client and server can handle.

Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
---
 fs/smb/client/reparse.c | 5 ++++-
 fs/smb/client/reparse.h | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

Comments

Steve French Nov. 18, 2024, 5:08 p.m. UTC | #1
Presumably a symlink could be up to PATH_MAX (4096), is there any
reason not to fix the client side to be able to handle at least 4096?

Any ideas how common long symlink target paths are?

On Mon, Nov 18, 2024 at 9:35 AM Paulo Alcantara <pc@manguebit.com> wrote:
>
> We can't use PATH_MAX for SMB symlinks because
>
>   (1) Windows Server will fail FSCTL_SET_REPARSE_POINT with
>       STATUS_IO_REPARSE_DATA_INVALID when input buffer is larger than
>       16K, as specified in MS-FSA 2.1.5.10.37.
>
>   (2) The client won't be able to parse large SMB responses that
>       includes SMB symlink path within SMB2_CREATE or SMB2_IOCTL
>       responses.
>
> Fix this by defining a maximum length value (4060) for SMB symlinks
> that both client and server can handle.
>
> Cc: David Howells <dhowells@redhat.com>
> Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
> ---
>  fs/smb/client/reparse.c | 5 ++++-
>  fs/smb/client/reparse.h | 2 ++
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index 74abbdf5026c..90da1e2b6217 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -35,6 +35,9 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
>         u16 len, plen;
>         int rc = 0;
>
> +       if (strlen(symname) > REPARSE_SYM_PATH_MAX)
> +               return -ENAMETOOLONG;
> +
>         sym = kstrdup(symname, GFP_KERNEL);
>         if (!sym)
>                 return -ENOMEM;
> @@ -64,7 +67,7 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
>         if (rc < 0)
>                 goto out;
>
> -       plen = 2 * UniStrnlen((wchar_t *)path, PATH_MAX);
> +       plen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX);
>         len = sizeof(*buf) + plen * 2;
>         buf = kzalloc(len, GFP_KERNEL);
>         if (!buf) {
> diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
> index 158e7b7aae64..2a9f4f9f79de 100644
> --- a/fs/smb/client/reparse.h
> +++ b/fs/smb/client/reparse.h
> @@ -12,6 +12,8 @@
>  #include "fs_context.h"
>  #include "cifsglob.h"
>
> +#define REPARSE_SYM_PATH_MAX 4060
> +
>  /*
>   * Used only by cifs.ko to ignore reparse points from files when client or
>   * server doesn't support FSCTL_GET_REPARSE_POINT.
> --
> 2.47.0
>
Paulo Alcantara Nov. 18, 2024, 6:59 p.m. UTC | #2
Steve French <smfrench@gmail.com> writes:

> Presumably a symlink could be up to PATH_MAX (4096), is there any
> reason not to fix the client side to be able to handle at least 4096?

Even if we fix client to handle larger responses, Windows Server will
not allow more than 4091 characters due to MS-FSA 2.1.5.10.37.  It's
even worst with encryption that we only support parsing large responses
with SMB2_READ.

Yes, we could fix the client to support up to 4091 chars, but that is
out of scope for this series.  This patch is for allowing users to
create SMB symlinks and read them back with and without encryption.
diff mbox series

Patch

diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 74abbdf5026c..90da1e2b6217 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -35,6 +35,9 @@  int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
 	u16 len, plen;
 	int rc = 0;
 
+	if (strlen(symname) > REPARSE_SYM_PATH_MAX)
+		return -ENAMETOOLONG;
+
 	sym = kstrdup(symname, GFP_KERNEL);
 	if (!sym)
 		return -ENOMEM;
@@ -64,7 +67,7 @@  int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
 	if (rc < 0)
 		goto out;
 
-	plen = 2 * UniStrnlen((wchar_t *)path, PATH_MAX);
+	plen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX);
 	len = sizeof(*buf) + plen * 2;
 	buf = kzalloc(len, GFP_KERNEL);
 	if (!buf) {
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
index 158e7b7aae64..2a9f4f9f79de 100644
--- a/fs/smb/client/reparse.h
+++ b/fs/smb/client/reparse.h
@@ -12,6 +12,8 @@ 
 #include "fs_context.h"
 #include "cifsglob.h"
 
+#define REPARSE_SYM_PATH_MAX 4060
+
 /*
  * Used only by cifs.ko to ignore reparse points from files when client or
  * server doesn't support FSCTL_GET_REPARSE_POINT.