[PATCH][SMB3]enumerating snapshots was leaving part of the data off end

Steve French smfrench at gmail.com
Thu Aug 9 06:32:42 UTC 2018


Here is sample output running a userspace tool against the patched kernel
mounted to a Windows volume with two snapshots
(before the second snapshot would be missing a few bytes at the end)

# ~/enum-snapshots /mnt/file
press enter to issue the ioctl to retrieve snapshot information ...

Num snapshots: 2 Num returned: 2 Array Size: 102

Snapshot 0:@GMT-2018.06.30-19.34.17
Snapshot 1:@GMT-2018.06.30-19.33.37
On Thu, Aug 9, 2018 at 1:00 AM Steve French <smfrench at gmail.com> wrote:
>
>     When enumerating snapshots, the last few bytes of the final
>     snapshot could be left off since we were miscalculating the
>     length returned (leaving off the sizeof struct SRV_SNAPSHOT_ARRAY)
>     See MS-SMB2 section 2.2.32.2. In addition fixup the length used
>     to allow smaller buffer to be passed in, in order to allow
>     returning the size of the whole snapshot array more easily.
>
>     CC: Stable <stable at vger.kernel.org>
>     Signed-off-by: Steve French <stfrench at microsoft.com>
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 15c7cbde2f39..abd6142e1b4a 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -1369,6 +1369,8 @@ smb3_set_integrity(const unsigned int xid,
> struct cifs_tcon *tcon,
>
>  }
>
> +/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
> +#define GMT_TOKEN_SIZE 50
>  static int
>  smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
>                    struct cifsFileInfo *cfile, void __user *ioc_buf)
> @@ -1398,14 +1400,25 @@ smb3_enum_snapshots(const unsigned int xid,
> struct cifs_tcon *tcon,
>                         kfree(retbuf);
>                         return rc;
>                 }
> -               if (snapshot_in.snapshot_array_size < sizeof(struct
> smb_snapshot_array)) {
> -                       rc = -ERANGE;
> -                       kfree(retbuf);
> -                       return rc;
> -               }
>
> -               if (ret_data_len > snapshot_in.snapshot_array_size)
> -                       ret_data_len = snapshot_in.snapshot_array_size;
> +               /* check for min size, ie not large enough to fit even one GMT
> +                * token (snapshot).  On the first ioctl some users may pass in
> +                * smaller size (or zero) to simply get the size of the array
> +                * so the user space caller can allocate sufficient memory
> +                * and retry the ioctl again with larger array size sufficient
> +                * to hold all of the snapshot GMT tokens on the second try.
> +                */
> +               if (snapshot_in.snapshot_array_size < GMT_TOKEN_SIZE)
> +                       ret_data_len = sizeof(struct smb_snapshot_array);
> +
> +               /* we return struct SRV_SNAPSHOT_ARRAY, followed by
> +                * the snapshot array (of 50 byte GMT tokens) each
> +                * representing an available previous version of the data
> +                */
> +               if (ret_data_len > (snapshot_in.snapshot_array_size +
> +                                       sizeof(struct smb_snapshot_array)))
> +                       ret_data_len = snapshot_in.snapshot_array_size +
> +                                       sizeof(struct smb_snapshot_array);
>
>                 if (copy_to_user(ioc_buf, retbuf, ret_data_len))
>                         rc = -EFAULT;
> (END)
>
>
> --
> Thanks,
>
> Steve



-- 
Thanks,

Steve



More information about the samba-technical mailing list