| From 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7 Mon Sep 17 00:00:00 2001 |
| From: Steve French <stfrench@microsoft.com> |
| Date: Sun, 24 Jun 2018 23:18:52 -0500 |
| Subject: smb3: fill in statfs fsid and correct namelen |
| |
| From: Steve French <stfrench@microsoft.com> |
| |
| commit 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7 upstream. |
| |
| Fil in the correct namelen (typically 255 not 4096) in the |
| statfs response and also fill in a reasonably unique fsid |
| (in this case taken from the volume id, and the creation time |
| of the volume). |
| |
| In the case of the POSIX statfs all fields are now filled in, |
| and in the case of non-POSIX mounts, all fields are filled |
| in which can be. |
| |
| Signed-off-by: Steve French <stfrench@gmail.com> |
| CC: Stable <stable@vger.kernel.org> |
| Reviewed-by: Aurelien Aptel <aaptel@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/cifs/cifsfs.c | 18 ++++++++++-------- |
| fs/cifs/smb2ops.c | 2 ++ |
| fs/cifs/smb2pdu.c | 8 ++++++++ |
| fs/cifs/smb2pdu.h | 11 +++++++++++ |
| 4 files changed, 31 insertions(+), 8 deletions(-) |
| |
| --- a/fs/cifs/cifsfs.c |
| +++ b/fs/cifs/cifsfs.c |
| @@ -197,14 +197,16 @@ cifs_statfs(struct dentry *dentry, struc |
| |
| xid = get_xid(); |
| |
| - /* |
| - * PATH_MAX may be too long - it would presumably be total path, |
| - * but note that some servers (includinng Samba 3) have a shorter |
| - * maximum path. |
| - * |
| - * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO. |
| - */ |
| - buf->f_namelen = PATH_MAX; |
| + if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0) |
| + buf->f_namelen = |
| + le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength); |
| + else |
| + buf->f_namelen = PATH_MAX; |
| + |
| + buf->f_fsid.val[0] = tcon->vol_serial_number; |
| + /* are using part of create time for more randomness, see man statfs */ |
| + buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time); |
| + |
| buf->f_files = 0; /* undefined */ |
| buf->f_ffree = 0; /* unlimited */ |
| |
| --- a/fs/cifs/smb2ops.c |
| +++ b/fs/cifs/smb2ops.c |
| @@ -333,6 +333,8 @@ smb3_qfs_tcon(const unsigned int xid, st |
| SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, |
| FS_DEVICE_INFORMATION); |
| SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, |
| + FS_VOLUME_INFORMATION); |
| + SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, |
| FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */ |
| SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
| return; |
| --- a/fs/cifs/smb2pdu.c |
| +++ b/fs/cifs/smb2pdu.c |
| @@ -3455,6 +3455,9 @@ SMB2_QFS_attr(const unsigned int xid, st |
| } else if (level == FS_SECTOR_SIZE_INFORMATION) { |
| max_len = sizeof(struct smb3_fs_ss_info); |
| min_len = sizeof(struct smb3_fs_ss_info); |
| + } else if (level == FS_VOLUME_INFORMATION) { |
| + max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN; |
| + min_len = sizeof(struct smb3_fs_vol_info); |
| } else { |
| cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level); |
| return -EINVAL; |
| @@ -3495,6 +3498,11 @@ SMB2_QFS_attr(const unsigned int xid, st |
| tcon->ss_flags = le32_to_cpu(ss_info->Flags); |
| tcon->perf_sector_size = |
| le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); |
| + } else if (level == FS_VOLUME_INFORMATION) { |
| + struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *) |
| + (offset + (char *)rsp); |
| + tcon->vol_serial_number = vol_info->VolumeSerialNumber; |
| + tcon->vol_create_time = vol_info->VolumeCreationTime; |
| } |
| |
| qfsattr_exit: |
| --- a/fs/cifs/smb2pdu.h |
| +++ b/fs/cifs/smb2pdu.h |
| @@ -1108,6 +1108,17 @@ struct smb3_fs_ss_info { |
| __le32 ByteOffsetForPartitionAlignment; |
| } __packed; |
| |
| +/* volume info struct - see MS-FSCC 2.5.9 */ |
| +#define MAX_VOL_LABEL_LEN 32 |
| +struct smb3_fs_vol_info { |
| + __le64 VolumeCreationTime; |
| + __u32 VolumeSerialNumber; |
| + __le32 VolumeLabelLength; /* includes trailing null */ |
| + __u8 SupportsObjects; /* True if eg like NTFS, supports objects */ |
| + __u8 Reserved; |
| + __u8 VolumeLabel[0]; /* variable len */ |
| +} __packed; |
| + |
| /* partial list of QUERY INFO levels */ |
| #define FILE_DIRECTORY_INFORMATION 1 |
| #define FILE_FULL_DIRECTORY_INFORMATION 2 |