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@xxxxxxxxx> 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@xxxxxxxxxxxxxxx> > Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> > > 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 -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html