diff mbox

Distinguishing between different types of reparse point symlinks

Message ID CAH2r5mvhJ+pqJTEV4Hc8QNzVu7WWXhdvuGUJiGrxp2C-GAe8OA@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Steve French Sept. 27, 2013, 5:58 a.m. UTC
I have to make some minor fixes to the patch below to account for
little endian specific fields in symlink reparse point structure, but
it does fix the problem ("ls -l" to windows 8 or later share which has
multiple types of reparse points in the same directory, not all of
which are NTFS symlinks).

From: Steve French <smfrench@gmail.com>
Date: Thu, 26 Sep 2013 19:49:14 -0500
Subject: [PATCH] [CIFS] do not treat non-symlink reparse points as valid
 symlinks

Windows 8 and later can create NFS symlinks (within reparse points)
which we were assuming were normal NTFS symlinks and thus reporting
corrupt paths for.  Add check for reparse points to make sure that
they really are normal symlinks before we try to parse the pathname.

This fixes commit d244bf2dfbebfded05f494ffd53659fa7b1e32c1
which implemented follow link for non-Unix CIFS mounts

CC: Stable <stable@kernel.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
---
 fs/cifs/cifspdu.h  |  2 +-
 fs/cifs/cifssmb.c  |  9 +++++++--
 fs/cifs/smbfsctl.h | 14 ++++++++++++++
 3 files changed, 22 insertions(+), 3 deletions(-)

Comments

Pavel Shilovsky Sept. 27, 2013, 6:13 a.m. UTC | #1
2013/9/27 Steve French <smfrench@gmail.com>:
> I have to make some minor fixes to the patch below to account for
> little endian specific fields in symlink reparse point structure, but
> it does fix the problem ("ls -l" to windows 8 or later share which has
> multiple types of reparse points in the same directory, not all of
> which are NTFS symlinks).
>
> From: Steve French <smfrench@gmail.com>
> Date: Thu, 26 Sep 2013 19:49:14 -0500
> Subject: [PATCH] [CIFS] do not treat non-symlink reparse points as valid
>  symlinks
>
> Windows 8 and later can create NFS symlinks (within reparse points)
> which we were assuming were normal NTFS symlinks and thus reporting
> corrupt paths for.  Add check for reparse points to make sure that
> they really are normal symlinks before we try to parse the pathname.
>
> This fixes commit d244bf2dfbebfded05f494ffd53659fa7b1e32c1
> which implemented follow link for non-Unix CIFS mounts
>
> CC: Stable <stable@kernel.org>
> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
> Signed-off-by: Steve French <smfrench@gmail.com>
> ---
>  fs/cifs/cifspdu.h  |  2 +-
>  fs/cifs/cifssmb.c  |  9 +++++++--
>  fs/cifs/smbfsctl.h | 14 ++++++++++++++
>  3 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
> index a630475..5f295f3 100644
> --- a/fs/cifs/cifspdu.h
> +++ b/fs/cifs/cifspdu.h
> @@ -1491,7 +1491,7 @@ struct file_notify_information {
>   __u8  FileName[0];
>  } __attribute__((packed));
>
> -struct reparse_data {
> +struct reparse_symlink_data {
>   __u32 ReparseTag;
>   __u16 ReparseDataLength;
>   __u16 Reserved;
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 4baf359..0bf7635 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -3088,7 +3088,7 @@ CIFSSMBQuerySymLink(const unsigned int xid,
> struct cifs_tcon *tcon,
>   bool is_unicode;
>   unsigned int sub_len;
>   char *sub_start;
> - struct reparse_data *reparse_buf;
> + struct reparse_symlink_data *reparse_buf;
>   __u32 data_offset, data_count;
>   char *end_of_smb;
>
> @@ -3137,12 +3137,17 @@ CIFSSMBQuerySymLink(const unsigned int xid,
> struct cifs_tcon *tcon,
>   goto qreparse_out;
>   }
>   end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
> - reparse_buf = (struct reparse_data *)
> + reparse_buf = (struct reparse_symlink_data *)
>   ((char *)&pSMBr->hdr.Protocol + data_offset);
>   if ((char *)reparse_buf >= end_of_smb) {
>   rc = -EIO;
>   goto qreparse_out;
>   }
> + if (reparse_buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
> + rc = -EOPNOTSUPP;
> + goto qreparse_out;
> + }
> +

Shouldn't we do the same things for SMB2?

>   if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
>   reparse_buf->PrintNameLength) > end_of_smb) {
>   cifs_dbg(FYI, "reparse buf beyond SMB\n");
> diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
> index d952ee4..3a10e1c 100644
> --- a/fs/cifs/smbfsctl.h
> +++ b/fs/cifs/smbfsctl.h
> @@ -97,9 +97,23 @@
>  #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
>  #define FSCTL_SRV_READ_HASH          0x001441BB /* BB add struct */
>
> +/* See FSCC 2.1.2.5 */
>  #define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
>  #define IO_REPARSE_TAG_HSM           0xC0000004
>  #define IO_REPARSE_TAG_SIS           0x80000007
> +#define IO_REPARSE_TAG_HSM2          0x80000006
> +#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
> +/* Used by the DFS filter. See MS-DFSC */
> +#define IO_REPARSE_TAG_DFS           0x8000000A
> +/* Used by the DFS filter See MS-DFSC */
> +#define IO_REPARSE_TAG_DFSR          0x80000012
> +#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
> +/* See section MS-FSCC 2.1.2.4 */
> +#define IO_REPARSE_TAG_SYMLINK       0xA000000C
> +#define IO_REPARSE_TAG_DEDUP         0x80000013
> +#define IO_REPARSE_APPXSTREAM     0xC0000014
> +/* NFS symlinks, Win 8/SMB3 and later */
> +#define IO_REPARSE_TAG_NFS           0xA0000014
>
>  /* fsctl flags */
>  /* If Flags is set to this value, the request is an FSCTL not ioctl request */
> --
> 1.7.11.7
>
>
> --
> Thanks,
>
> Steve
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index a630475..5f295f3 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1491,7 +1491,7 @@  struct file_notify_information {
  __u8  FileName[0];
 } __attribute__((packed));

-struct reparse_data {
+struct reparse_symlink_data {
  __u32 ReparseTag;
  __u16 ReparseDataLength;
  __u16 Reserved;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 4baf359..0bf7635 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3088,7 +3088,7 @@  CIFSSMBQuerySymLink(const unsigned int xid,
struct cifs_tcon *tcon,
  bool is_unicode;
  unsigned int sub_len;
  char *sub_start;
- struct reparse_data *reparse_buf;
+ struct reparse_symlink_data *reparse_buf;
  __u32 data_offset, data_count;
  char *end_of_smb;

@@ -3137,12 +3137,17 @@  CIFSSMBQuerySymLink(const unsigned int xid,
struct cifs_tcon *tcon,
  goto qreparse_out;
  }
  end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
- reparse_buf = (struct reparse_data *)
+ reparse_buf = (struct reparse_symlink_data *)
  ((char *)&pSMBr->hdr.Protocol + data_offset);
  if ((char *)reparse_buf >= end_of_smb) {
  rc = -EIO;
  goto qreparse_out;
  }
+ if (reparse_buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
+ rc = -EOPNOTSUPP;
+ goto qreparse_out;
+ }
+
  if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
  reparse_buf->PrintNameLength) > end_of_smb) {
  cifs_dbg(FYI, "reparse buf beyond SMB\n");
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
index d952ee4..3a10e1c 100644
--- a/fs/cifs/smbfsctl.h
+++ b/fs/cifs/smbfsctl.h
@@ -97,9 +97,23 @@ 
 #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
 #define FSCTL_SRV_READ_HASH          0x001441BB /* BB add struct */

+/* See FSCC 2.1.2.5 */
 #define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
 #define IO_REPARSE_TAG_HSM           0xC0000004
 #define IO_REPARSE_TAG_SIS           0x80000007
+#define IO_REPARSE_TAG_HSM2          0x80000006
+#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
+/* Used by the DFS filter. See MS-DFSC */
+#define IO_REPARSE_TAG_DFS           0x8000000A
+/* Used by the DFS filter See MS-DFSC */
+#define IO_REPARSE_TAG_DFSR          0x80000012
+#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
+/* See section MS-FSCC 2.1.2.4 */
+#define IO_REPARSE_TAG_SYMLINK       0xA000000C
+#define IO_REPARSE_TAG_DEDUP         0x80000013
+#define IO_REPARSE_APPXSTREAM     0xC0000014
+/* NFS symlinks, Win 8/SMB3 and later */
+#define IO_REPARSE_TAG_NFS           0xA0000014

 /* fsctl flags */
 /* If Flags is set to this value, the request is an FSCTL not ioctl request */