Skip to content

Commit 1dd5c6b

Browse files
committed
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "This ncludes various cifs/smb3 bug fixes, mostly for stable as well. In the next week I expect that Germano will have some reconnection fixes, and also I expect to have the remaining pieces of the snapshot enablement and SMB3 ACLs, but wanted to get this set of bug fixes in" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: cifs_get_root shouldn't use path with tree name Fix default behaviour for empty domains and add domainauto option cifs: use %16phN for formatting md5 sum cifs: Fix smbencrypt() to stop pointing a scatterlist at the stack CIFS: Fix a possible double locking of mutex during reconnect CIFS: Fix a possible memory corruption during reconnect CIFS: Fix a possible memory corruption in push locks CIFS: Fix missing nls unload in smb2_reconnect() CIFS: Decrease verbosity of ioctl call SMB3: parsing for new snapshot timestamp mount parm
2 parents 3a77fa8 + 374402a commit 1dd5c6b

File tree

14 files changed

+177
-90
lines changed

14 files changed

+177
-90
lines changed

fs/cifs/cifsencrypt.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -699,11 +699,15 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
699699

700700
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
701701
if (!ses->domainName) {
702-
rc = find_domain_name(ses, nls_cp);
703-
if (rc) {
704-
cifs_dbg(VFS, "error %d finding domain name\n",
705-
rc);
706-
goto setup_ntlmv2_rsp_ret;
702+
if (ses->domainAuto) {
703+
rc = find_domain_name(ses, nls_cp);
704+
if (rc) {
705+
cifs_dbg(VFS, "error %d finding domain name\n",
706+
rc);
707+
goto setup_ntlmv2_rsp_ret;
708+
}
709+
} else {
710+
ses->domainName = kstrdup("", GFP_KERNEL);
707711
}
708712
}
709713
} else {

fs/cifs/cifsfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
615615
return dget(sb->s_root);
616616

617617
full_path = cifs_build_path_to_root(vol, cifs_sb,
618-
cifs_sb_master_tcon(cifs_sb));
618+
cifs_sb_master_tcon(cifs_sb), 0);
619619
if (full_path == NULL)
620620
return ERR_PTR(-ENOMEM);
621621

fs/cifs/cifsglob.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ struct smb_vol {
514514
bool persistent:1;
515515
bool nopersistent:1;
516516
bool resilient:1; /* noresilient not required since not fored for CA */
517+
bool domainauto:1;
517518
unsigned int rsize;
518519
unsigned int wsize;
519520
bool sockopt_tcp_nodelay:1;
@@ -525,6 +526,7 @@ struct smb_vol {
525526
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
526527
struct nls_table *local_nls;
527528
unsigned int echo_interval; /* echo interval in secs */
529+
__u64 snapshot_time; /* needed for timewarp tokens */
528530
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
529531
};
530532

@@ -646,6 +648,8 @@ struct TCP_Server_Info {
646648
unsigned int max_read;
647649
unsigned int max_write;
648650
__u8 preauth_hash[512];
651+
struct delayed_work reconnect; /* reconnect workqueue job */
652+
struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
649653
#endif /* CONFIG_CIFS_SMB2 */
650654
unsigned long echo_interval;
651655
};
@@ -827,6 +831,7 @@ struct cifs_ses {
827831
enum securityEnum sectype; /* what security flavor was specified? */
828832
bool sign; /* is signing required? */
829833
bool need_reconnect:1; /* connection reset, uid now invalid */
834+
bool domainAuto:1;
830835
#ifdef CONFIG_CIFS_SMB2
831836
__u16 session_flags;
832837
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
@@ -849,6 +854,7 @@ cap_unix(struct cifs_ses *ses)
849854
struct cifs_tcon {
850855
struct list_head tcon_list;
851856
int tc_count;
857+
struct list_head rlist; /* reconnect list */
852858
struct list_head openFileList;
853859
spinlock_t open_file_lock; /* protects list above */
854860
struct cifs_ses *ses; /* pointer to session associated with */
@@ -922,6 +928,7 @@ struct cifs_tcon {
922928
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
923929
bool broken_sparse_sup; /* if server or share does not support sparse */
924930
bool need_reconnect:1; /* connection reset, tid now invalid */
931+
bool need_reopen_files:1; /* need to reopen tcon file handles */
925932
bool use_resilient:1; /* use resilient instead of durable handles */
926933
bool use_persistent:1; /* use persistent instead of durable handles */
927934
#ifdef CONFIG_CIFS_SMB2
@@ -932,6 +939,7 @@ struct cifs_tcon {
932939
__u32 maximal_access;
933940
__u32 vol_serial_number;
934941
__le64 vol_create_time;
942+
__u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
935943
__u32 ss_flags; /* sector size flags */
936944
__u32 perf_sector_size; /* best sector size for perf */
937945
__u32 max_chunks;

fs/cifs/cifsproto.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ extern void exit_cifs_spnego(void);
6363
extern char *build_path_from_dentry(struct dentry *);
6464
extern char *cifs_build_path_to_root(struct smb_vol *vol,
6565
struct cifs_sb_info *cifs_sb,
66-
struct cifs_tcon *tcon);
66+
struct cifs_tcon *tcon,
67+
int add_treename);
6768
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
6869
extern char *cifs_compose_mount_options(const char *sb_mountdata,
6970
const char *fullpath, const struct dfs_info3_param *ref,
@@ -206,6 +207,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
206207
struct tcon_link *tlink,
207208
struct cifs_pending_open *open);
208209
extern void cifs_del_pending_open(struct cifs_pending_open *open);
210+
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
211+
int from_reconnect);
212+
extern void cifs_put_tcon(struct cifs_tcon *tcon);
209213

210214
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
211215
extern void cifs_dfs_release_automount_timer(void);

fs/cifs/connect.c

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
#include "nterr.h"
5454
#include "rfc1002pdu.h"
5555
#include "fscache.h"
56+
#ifdef CONFIG_CIFS_SMB2
57+
#include "smb2proto.h"
58+
#endif
5659

5760
#define CIFS_PORT 445
5861
#define RFC1001_PORT 139
@@ -89,13 +92,15 @@ enum {
8992
Opt_multiuser, Opt_sloppy, Opt_nosharesock,
9093
Opt_persistent, Opt_nopersistent,
9194
Opt_resilient, Opt_noresilient,
95+
Opt_domainauto,
9296

9397
/* Mount options which take numeric value */
9498
Opt_backupuid, Opt_backupgid, Opt_uid,
9599
Opt_cruid, Opt_gid, Opt_file_mode,
96100
Opt_dirmode, Opt_port,
97101
Opt_rsize, Opt_wsize, Opt_actimeo,
98102
Opt_echo_interval, Opt_max_credits,
103+
Opt_snapshot,
99104

100105
/* Mount options which take string value */
101106
Opt_user, Opt_pass, Opt_ip,
@@ -177,6 +182,7 @@ static const match_table_t cifs_mount_option_tokens = {
177182
{ Opt_nopersistent, "nopersistenthandles"},
178183
{ Opt_resilient, "resilienthandles"},
179184
{ Opt_noresilient, "noresilienthandles"},
185+
{ Opt_domainauto, "domainauto"},
180186

181187
{ Opt_backupuid, "backupuid=%s" },
182188
{ Opt_backupgid, "backupgid=%s" },
@@ -192,6 +198,7 @@ static const match_table_t cifs_mount_option_tokens = {
192198
{ Opt_actimeo, "actimeo=%s" },
193199
{ Opt_echo_interval, "echo_interval=%s" },
194200
{ Opt_max_credits, "max_credits=%s" },
201+
{ Opt_snapshot, "snapshot=%s" },
195202

196203
{ Opt_blank_user, "user=" },
197204
{ Opt_blank_user, "username=" },
@@ -1500,6 +1507,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
15001507
case Opt_noresilient:
15011508
vol->resilient = false; /* already the default */
15021509
break;
1510+
case Opt_domainauto:
1511+
vol->domainauto = true;
1512+
break;
15031513

15041514
/* Numeric Values */
15051515
case Opt_backupuid:
@@ -1602,6 +1612,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
16021612
}
16031613
vol->echo_interval = option;
16041614
break;
1615+
case Opt_snapshot:
1616+
if (get_option_ul(args, &option)) {
1617+
cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1618+
__func__);
1619+
goto cifs_parse_mount_err;
1620+
}
1621+
vol->snapshot_time = option;
1622+
break;
16051623
case Opt_max_credits:
16061624
if (get_option_ul(args, &option) || (option < 20) ||
16071625
(option > 60000)) {
@@ -2101,8 +2119,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
21012119
return NULL;
21022120
}
21032121

2104-
static void
2105-
cifs_put_tcp_session(struct TCP_Server_Info *server)
2122+
void
2123+
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
21062124
{
21072125
struct task_struct *task;
21082126

@@ -2119,6 +2137,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
21192137

21202138
cancel_delayed_work_sync(&server->echo);
21212139

2140+
#ifdef CONFIG_CIFS_SMB2
2141+
if (from_reconnect)
2142+
/*
2143+
* Avoid deadlock here: reconnect work calls
2144+
* cifs_put_tcp_session() at its end. Need to be sure
2145+
* that reconnect work does nothing with server pointer after
2146+
* that step.
2147+
*/
2148+
cancel_delayed_work(&server->reconnect);
2149+
else
2150+
cancel_delayed_work_sync(&server->reconnect);
2151+
#endif
2152+
21222153
spin_lock(&GlobalMid_Lock);
21232154
server->tcpStatus = CifsExiting;
21242155
spin_unlock(&GlobalMid_Lock);
@@ -2183,6 +2214,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
21832214
INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
21842215
INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
21852216
INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
2217+
#ifdef CONFIG_CIFS_SMB2
2218+
INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2219+
mutex_init(&tcp_ses->reconnect_mutex);
2220+
#endif
21862221
memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
21872222
sizeof(tcp_ses->srcaddr));
21882223
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
@@ -2341,7 +2376,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
23412376
spin_unlock(&cifs_tcp_ses_lock);
23422377

23432378
sesInfoFree(ses);
2344-
cifs_put_tcp_session(server);
2379+
cifs_put_tcp_session(server, 0);
23452380
}
23462381

23472382
#ifdef CONFIG_KEYS
@@ -2515,7 +2550,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
25152550
mutex_unlock(&ses->session_mutex);
25162551

25172552
/* existing SMB ses has a server reference already */
2518-
cifs_put_tcp_session(server);
2553+
cifs_put_tcp_session(server, 0);
25192554
free_xid(xid);
25202555
return ses;
25212556
}
@@ -2549,6 +2584,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
25492584
if (!ses->domainName)
25502585
goto get_ses_fail;
25512586
}
2587+
if (volume_info->domainauto)
2588+
ses->domainAuto = volume_info->domainauto;
25522589
ses->cred_uid = volume_info->cred_uid;
25532590
ses->linux_uid = volume_info->linux_uid;
25542591

@@ -2587,16 +2624,22 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc)
25872624
}
25882625

25892626
static struct cifs_tcon *
2590-
cifs_find_tcon(struct cifs_ses *ses, const char *unc)
2627+
cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
25912628
{
25922629
struct list_head *tmp;
25932630
struct cifs_tcon *tcon;
25942631

25952632
spin_lock(&cifs_tcp_ses_lock);
25962633
list_for_each(tmp, &ses->tcon_list) {
25972634
tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
2598-
if (!match_tcon(tcon, unc))
2635+
if (!match_tcon(tcon, volume_info->UNC))
25992636
continue;
2637+
2638+
#ifdef CONFIG_CIFS_SMB2
2639+
if (tcon->snapshot_time != volume_info->snapshot_time)
2640+
continue;
2641+
#endif /* CONFIG_CIFS_SMB2 */
2642+
26002643
++tcon->tc_count;
26012644
spin_unlock(&cifs_tcp_ses_lock);
26022645
return tcon;
@@ -2605,7 +2648,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
26052648
return NULL;
26062649
}
26072650

2608-
static void
2651+
void
26092652
cifs_put_tcon(struct cifs_tcon *tcon)
26102653
{
26112654
unsigned int xid;
@@ -2637,7 +2680,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
26372680
int rc, xid;
26382681
struct cifs_tcon *tcon;
26392682

2640-
tcon = cifs_find_tcon(ses, volume_info->UNC);
2683+
tcon = cifs_find_tcon(ses, volume_info);
26412684
if (tcon) {
26422685
cifs_dbg(FYI, "Found match on UNC path\n");
26432686
/* existing tcon already has a reference */
@@ -2658,6 +2701,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
26582701
goto out_fail;
26592702
}
26602703

2704+
if (volume_info->snapshot_time) {
2705+
#ifdef CONFIG_CIFS_SMB2
2706+
if (ses->server->vals->protocol_id == 0) {
2707+
cifs_dbg(VFS,
2708+
"Use SMB2 or later for snapshot mount option\n");
2709+
rc = -EOPNOTSUPP;
2710+
goto out_fail;
2711+
} else
2712+
tcon->snapshot_time = volume_info->snapshot_time;
2713+
#else
2714+
cifs_dbg(VFS, "Snapshot mount option requires SMB2 support\n");
2715+
rc = -EOPNOTSUPP;
2716+
goto out_fail;
2717+
#endif /* CONFIG_CIFS_SMB2 */
2718+
}
2719+
26612720
tcon->ses = ses;
26622721
if (volume_info->password) {
26632722
tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
@@ -3707,7 +3766,8 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
37073766
/*
37083767
* cifs_build_path_to_root works only when we have a valid tcon
37093768
*/
3710-
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
3769+
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
3770+
tcon->Flags & SMB_SHARE_IS_IN_DFS);
37113771
if (full_path == NULL) {
37123772
rc = -ENOMEM;
37133773
goto mount_fail_check;
@@ -3793,7 +3853,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
37933853
else if (ses)
37943854
cifs_put_smb_ses(ses);
37953855
else
3796-
cifs_put_tcp_session(server);
3856+
cifs_put_tcp_session(server, 0);
37973857
bdi_destroy(&cifs_sb->bdi);
37983858
}
37993859

@@ -4104,7 +4164,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
41044164
ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
41054165
if (IS_ERR(ses)) {
41064166
tcon = (struct cifs_tcon *)ses;
4107-
cifs_put_tcp_session(master_tcon->ses->server);
4167+
cifs_put_tcp_session(master_tcon->ses->server, 0);
41084168
goto out;
41094169
}
41104170

fs/cifs/dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ renew_parental_timestamps(struct dentry *direntry)
4747

4848
char *
4949
cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
50-
struct cifs_tcon *tcon)
50+
struct cifs_tcon *tcon, int add_treename)
5151
{
5252
int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
5353
int dfsplen;
@@ -59,7 +59,7 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
5959
return full_path;
6060
}
6161

62-
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
62+
if (add_treename)
6363
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
6464
else
6565
dfsplen = 0;

fs/cifs/file.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,11 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
777777
struct list_head *tmp1;
778778
struct list_head tmp_list;
779779

780+
if (!tcon->use_persistent || !tcon->need_reopen_files)
781+
return;
782+
783+
tcon->need_reopen_files = false;
784+
780785
cifs_dbg(FYI, "Reopen persistent handles");
781786
INIT_LIST_HEAD(&tmp_list);
782787

@@ -793,7 +798,8 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
793798

794799
list_for_each_safe(tmp, tmp1, &tmp_list) {
795800
open_file = list_entry(tmp, struct cifsFileInfo, rlist);
796-
cifs_reopen_file(open_file, false /* do not flush */);
801+
if (cifs_reopen_file(open_file, false /* do not flush */))
802+
tcon->need_reopen_files = true;
797803
list_del_init(&open_file->rlist);
798804
cifsFileInfo_put(open_file);
799805
}

fs/cifs/ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
189189
xid = get_xid();
190190

191191
cifs_sb = CIFS_SB(inode->i_sb);
192-
cifs_dbg(VFS, "cifs ioctl 0x%x\n", command);
192+
cifs_dbg(FYI, "cifs ioctl 0x%x\n", command);
193193
switch (command) {
194194
case FS_IOC_GETFLAGS:
195195
if (pSMBFile == NULL)

0 commit comments

Comments
 (0)