Skip to content

Commit 145f47c

Browse files
committed
Merge tag '5.1-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb3 fixes from Steve French: "Four smb3 fixes for stable: - fix an open path where we had an unitialized structure - fix for snapshot (previous version) enumeration - allow reconnect timeout on handles to be configurable to better handle network or server crash - correctly handle lack of file_all_info structure" * tag '5.1-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: a smb2_validate_and_copy_iov failure does not mean the handle is invalid. SMB3: Allow persistent handle timeout to be configurable on mount smb3: Fix enumerating snapshots to Azure cifs: fix kref underflow in close_shroot()
2 parents 8ed8662 + 4811e30 commit 145f47c

File tree

7 files changed

+121
-47
lines changed

7 files changed

+121
-47
lines changed

fs/cifs/cifsfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
559559
tcon->ses->server->echo_interval / HZ);
560560
if (tcon->snapshot_time)
561561
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
562+
if (tcon->handle_timeout)
563+
seq_printf(s, ",handletimeout=%u", tcon->handle_timeout);
562564
/* convert actimeo and display it in seconds */
563565
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
564566

fs/cifs/cifsglob.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@
5959
*/
6060
#define CIFS_MAX_ACTIMEO (1 << 30)
6161

62+
/*
63+
* Max persistent and resilient handle timeout (milliseconds).
64+
* Windows durable max was 960000 (16 minutes)
65+
*/
66+
#define SMB3_MAX_HANDLE_TIMEOUT 960000
67+
6268
/*
6369
* MAX_REQ is the maximum number of requests that WE will send
6470
* on one socket concurrently.
@@ -586,6 +592,7 @@ struct smb_vol {
586592
struct nls_table *local_nls;
587593
unsigned int echo_interval; /* echo interval in secs */
588594
__u64 snapshot_time; /* needed for timewarp tokens */
595+
__u32 handle_timeout; /* persistent and durable handle timeout in ms */
589596
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
590597
};
591598

@@ -1058,6 +1065,7 @@ struct cifs_tcon {
10581065
__u32 vol_serial_number;
10591066
__le64 vol_create_time;
10601067
__u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
1068+
__u32 handle_timeout; /* persistent and durable handle timeout in ms */
10611069
__u32 ss_flags; /* sector size flags */
10621070
__u32 perf_sector_size; /* best sector size for perf */
10631071
__u32 max_chunks;

fs/cifs/connect.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ enum {
103103
Opt_cruid, Opt_gid, Opt_file_mode,
104104
Opt_dirmode, Opt_port,
105105
Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
106-
Opt_echo_interval, Opt_max_credits,
106+
Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
107107
Opt_snapshot,
108108

109109
/* Mount options which take string value */
@@ -208,6 +208,7 @@ static const match_table_t cifs_mount_option_tokens = {
208208
{ Opt_rsize, "rsize=%s" },
209209
{ Opt_wsize, "wsize=%s" },
210210
{ Opt_actimeo, "actimeo=%s" },
211+
{ Opt_handletimeout, "handletimeout=%s" },
211212
{ Opt_echo_interval, "echo_interval=%s" },
212213
{ Opt_max_credits, "max_credits=%s" },
213214
{ Opt_snapshot, "snapshot=%s" },
@@ -1619,6 +1620,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
16191620

16201621
vol->actimeo = CIFS_DEF_ACTIMEO;
16211622

1623+
/* Most clients set timeout to 0, allows server to use its default */
1624+
vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1625+
16221626
/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
16231627
vol->ops = &smb30_operations;
16241628
vol->vals = &smbdefault_values;
@@ -2017,6 +2021,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
20172021
goto cifs_parse_mount_err;
20182022
}
20192023
break;
2024+
case Opt_handletimeout:
2025+
if (get_option_ul(args, &option)) {
2026+
cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2027+
__func__);
2028+
goto cifs_parse_mount_err;
2029+
}
2030+
vol->handle_timeout = option;
2031+
if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2032+
cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2033+
goto cifs_parse_mount_err;
2034+
}
2035+
break;
20202036
case Opt_echo_interval:
20212037
if (get_option_ul(args, &option)) {
20222038
cifs_dbg(VFS, "%s: Invalid echo interval value\n",
@@ -3183,6 +3199,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
31833199
return 0;
31843200
if (tcon->snapshot_time != volume_info->snapshot_time)
31853201
return 0;
3202+
if (tcon->handle_timeout != volume_info->handle_timeout)
3203+
return 0;
31863204
return 1;
31873205
}
31883206

@@ -3297,6 +3315,16 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
32973315
tcon->snapshot_time = volume_info->snapshot_time;
32983316
}
32993317

3318+
if (volume_info->handle_timeout) {
3319+
if (ses->server->vals->protocol_id == 0) {
3320+
cifs_dbg(VFS,
3321+
"Use SMB2.1 or later for handle timeout option\n");
3322+
rc = -EOPNOTSUPP;
3323+
goto out_fail;
3324+
} else
3325+
tcon->handle_timeout = volume_info->handle_timeout;
3326+
}
3327+
33003328
tcon->ses = ses;
33013329
if (volume_info->password) {
33023330
tcon->password = kstrdup(volume_info->password, GFP_KERNEL);

fs/cifs/smb2file.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,15 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
6868

6969

7070
if (oparms->tcon->use_resilient) {
71-
nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
71+
/* default timeout is 0, servers pick default (120 seconds) */
72+
nr_ioctl_req.Timeout =
73+
cpu_to_le32(oparms->tcon->handle_timeout);
7274
nr_ioctl_req.Reserved = 0;
7375
rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
7476
fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
7577
true /* is_fsctl */,
7678
(char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
77-
NULL, NULL /* no return info */);
79+
CIFSMaxBufSize, NULL, NULL /* no return info */);
7880
if (rc == -EOPNOTSUPP) {
7981
cifs_dbg(VFS,
8082
"resiliency not supported by server, disabling\n");

fs/cifs/smb2ops.c

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
581581
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
582582
FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
583583
NULL /* no data input */, 0 /* no data input */,
584-
(char **)&out_buf, &ret_data_len);
584+
CIFSMaxBufSize, (char **)&out_buf, &ret_data_len);
585585
if (rc == -EOPNOTSUPP) {
586586
cifs_dbg(FYI,
587587
"server does not support query network interfaces\n");
@@ -717,32 +717,28 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
717717
oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId);
718718
#endif /* CIFS_DEBUG2 */
719719

720-
if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)
721-
oplock = smb2_parse_lease_state(server, o_rsp,
722-
&oparms.fid->epoch,
723-
oparms.fid->lease_key);
724-
else
725-
goto oshr_exit;
726-
727-
728720
memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid));
729721
tcon->crfid.tcon = tcon;
730722
tcon->crfid.is_valid = true;
731723
kref_init(&tcon->crfid.refcount);
732-
kref_get(&tcon->crfid.refcount);
733724

725+
if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
726+
kref_get(&tcon->crfid.refcount);
727+
oplock = smb2_parse_lease_state(server, o_rsp,
728+
&oparms.fid->epoch,
729+
oparms.fid->lease_key);
730+
} else
731+
goto oshr_exit;
734732

735733
qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
736734
if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info))
737735
goto oshr_exit;
738-
rc = smb2_validate_and_copy_iov(
736+
if (!smb2_validate_and_copy_iov(
739737
le16_to_cpu(qi_rsp->OutputBufferOffset),
740738
sizeof(struct smb2_file_all_info),
741739
&rsp_iov[1], sizeof(struct smb2_file_all_info),
742-
(char *)&tcon->crfid.file_all_info);
743-
if (rc)
744-
goto oshr_exit;
745-
tcon->crfid.file_all_info_is_valid = 1;
740+
(char *)&tcon->crfid.file_all_info))
741+
tcon->crfid.file_all_info_is_valid = 1;
746742

747743
oshr_exit:
748744
mutex_unlock(&tcon->crfid.fid_mutex);
@@ -1299,7 +1295,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
12991295

13001296
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
13011297
FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
1302-
NULL, 0 /* no input */,
1298+
NULL, 0 /* no input */, CIFSMaxBufSize,
13031299
(char **)&res_key, &ret_data_len);
13041300

13051301
if (rc) {
@@ -1404,7 +1400,7 @@ smb2_ioctl_query_info(const unsigned int xid,
14041400
rc = SMB2_ioctl_init(tcon, &rqst[1],
14051401
COMPOUND_FID, COMPOUND_FID,
14061402
qi.info_type, true, NULL,
1407-
0);
1403+
0, CIFSMaxBufSize);
14081404
}
14091405
} else if (qi.flags == PASSTHRU_QUERY_INFO) {
14101406
memset(&qi_iov, 0, sizeof(qi_iov));
@@ -1532,8 +1528,8 @@ smb2_copychunk_range(const unsigned int xid,
15321528
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
15331529
trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
15341530
true /* is_fsctl */, (char *)pcchunk,
1535-
sizeof(struct copychunk_ioctl), (char **)&retbuf,
1536-
&ret_data_len);
1531+
sizeof(struct copychunk_ioctl), CIFSMaxBufSize,
1532+
(char **)&retbuf, &ret_data_len);
15371533
if (rc == 0) {
15381534
if (ret_data_len !=
15391535
sizeof(struct copychunk_ioctl_rsp)) {
@@ -1693,7 +1689,7 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
16931689
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
16941690
cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
16951691
true /* is_fctl */,
1696-
&setsparse, 1, NULL, NULL);
1692+
&setsparse, 1, CIFSMaxBufSize, NULL, NULL);
16971693
if (rc) {
16981694
tcon->broken_sparse_sup = true;
16991695
cifs_dbg(FYI, "set sparse rc = %d\n", rc);
@@ -1766,7 +1762,7 @@ smb2_duplicate_extents(const unsigned int xid,
17661762
true /* is_fsctl */,
17671763
(char *)&dup_ext_buf,
17681764
sizeof(struct duplicate_extents_to_file),
1769-
NULL,
1765+
CIFSMaxBufSize, NULL,
17701766
&ret_data_len);
17711767

17721768
if (ret_data_len > 0)
@@ -1801,14 +1797,16 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
18011797
true /* is_fsctl */,
18021798
(char *)&integr_info,
18031799
sizeof(struct fsctl_set_integrity_information_req),
1804-
NULL,
1800+
CIFSMaxBufSize, NULL,
18051801
&ret_data_len);
18061802

18071803
}
18081804

18091805
/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
18101806
#define GMT_TOKEN_SIZE 50
18111807

1808+
#define MIN_SNAPSHOT_ARRAY_SIZE 16 /* See MS-SMB2 section 3.3.5.15.1 */
1809+
18121810
/*
18131811
* Input buffer contains (empty) struct smb_snapshot array with size filled in
18141812
* For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2
@@ -1820,13 +1818,29 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
18201818
char *retbuf = NULL;
18211819
unsigned int ret_data_len = 0;
18221820
int rc;
1821+
u32 max_response_size;
18231822
struct smb_snapshot_array snapshot_in;
18241823

1824+
if (get_user(ret_data_len, (unsigned int __user *)ioc_buf))
1825+
return -EFAULT;
1826+
1827+
/*
1828+
* Note that for snapshot queries that servers like Azure expect that
1829+
* the first query be minimal size (and just used to get the number/size
1830+
* of previous versions) so response size must be specified as EXACTLY
1831+
* sizeof(struct snapshot_array) which is 16 when rounded up to multiple
1832+
* of eight bytes.
1833+
*/
1834+
if (ret_data_len == 0)
1835+
max_response_size = MIN_SNAPSHOT_ARRAY_SIZE;
1836+
else
1837+
max_response_size = CIFSMaxBufSize;
1838+
18251839
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
18261840
cfile->fid.volatile_fid,
18271841
FSCTL_SRV_ENUMERATE_SNAPSHOTS,
18281842
true /* is_fsctl */,
1829-
NULL, 0 /* no input data */,
1843+
NULL, 0 /* no input data */, max_response_size,
18301844
(char **)&retbuf,
18311845
&ret_data_len);
18321846
cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
@@ -2304,7 +2318,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
23042318
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
23052319
FSCTL_DFS_GET_REFERRALS,
23062320
true /* is_fsctl */,
2307-
(char *)dfs_req, dfs_req_size,
2321+
(char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
23082322
(char **)&dfs_rsp, &dfs_rsp_size);
23092323
} while (rc == -EAGAIN);
23102324

@@ -2658,7 +2672,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
26582672
rc = SMB2_ioctl_init(tcon, &rqst[num++], cfile->fid.persistent_fid,
26592673
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
26602674
true /* is_fctl */, (char *)&fsctl_buf,
2661-
sizeof(struct file_zero_data_information));
2675+
sizeof(struct file_zero_data_information),
2676+
CIFSMaxBufSize);
26622677
if (rc)
26632678
goto zero_range_exit;
26642679

@@ -2735,7 +2750,8 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
27352750
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
27362751
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
27372752
true /* is_fctl */, (char *)&fsctl_buf,
2738-
sizeof(struct file_zero_data_information), NULL, NULL);
2753+
sizeof(struct file_zero_data_information),
2754+
CIFSMaxBufSize, NULL, NULL);
27392755
free_xid(xid);
27402756
return rc;
27412757
}

0 commit comments

Comments
 (0)