aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2014-05-12 19:48:12 -0400
committerSteve French <smfrench@gmail.com>2014-05-21 13:18:05 -0400
commit39552ea8120a699dbd0360848c4d949f9f0e6deb (patch)
treec9e3eccdcefdbcf1bd7f139f0c12945150912488
parent179d61839bafa924ff6f1960436339abdc911650 (diff)
cifs: Set client guid on per connection basis
When mounting from a Windows 2012R2 server, we hit the following problem: 1) Mount with any of the following versions - 2.0, 2.1 or 3.0 2) unmount 3) Attempt a mount again using a different SMB version >= 2.0. You end up with the following failure: Status code returned 0xc0000203 STATUS_USER_SESSION_DELETED CIFS VFS: Send error in SessSetup = -5 CIFS VFS: cifs_mount failed w/return code = -5 I cannot reproduce this issue using a Windows 2008 R2 server. This appears to be caused because we use the same client guid for the connection on first mount which we then disconnect and attempt to mount again using a different protocol version. By generating a new guid each time a new connection is Negotiated, we avoid hitting this problem. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/cifsfs.c8
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/smb2pdu.c5
-rw-r--r--fs/cifs/smb2pdu.h2
5 files changed, 7 insertions, 12 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index be66533c0f58..6aaa8112c538 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -87,10 +87,6 @@ extern mempool_t *cifs_mid_poolp;
87 87
88struct workqueue_struct *cifsiod_wq; 88struct workqueue_struct *cifsiod_wq;
89 89
90#ifdef CONFIG_CIFS_SMB2
91__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
92#endif
93
94/* 90/*
95 * Bumps refcount for cifs super block. 91 * Bumps refcount for cifs super block.
96 * Note that it should be only called if a referece to VFS super block is 92 * Note that it should be only called if a referece to VFS super block is
@@ -1188,10 +1184,6 @@ init_cifs(void)
1188 spin_lock_init(&cifs_file_list_lock); 1184 spin_lock_init(&cifs_file_list_lock);
1189 spin_lock_init(&GlobalMid_Lock); 1185 spin_lock_init(&GlobalMid_Lock);
1190 1186
1191#ifdef CONFIG_CIFS_SMB2
1192 get_random_bytes(cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
1193#endif
1194
1195 if (cifs_max_pending < 2) { 1187 if (cifs_max_pending < 2) {
1196 cifs_max_pending = 2; 1188 cifs_max_pending = 2;
1197 cifs_dbg(FYI, "cifs_max_pending set to min of 2\n"); 1189 cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 630e0f4b2c66..de6aed8c78e5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -559,6 +559,7 @@ struct TCP_Server_Info {
559 int echo_credits; /* echo reserved slots */ 559 int echo_credits; /* echo reserved slots */
560 int oplock_credits; /* oplock break reserved slots */ 560 int oplock_credits; /* oplock break reserved slots */
561 bool echoes:1; /* enable echoes */ 561 bool echoes:1; /* enable echoes */
562 __u8 client_guid[SMB2_CLIENT_GUID_SIZE]; /* Client GUID */
562#endif 563#endif
563 u16 dialect; /* dialect index that server chose */ 564 u16 dialect; /* dialect index that server chose */
564 bool oplocks:1; /* enable oplocks */ 565 bool oplocks:1; /* enable oplocks */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8813ff776ba3..8b8fe9b373f2 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2144,6 +2144,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
2144 sizeof(tcp_ses->srcaddr)); 2144 sizeof(tcp_ses->srcaddr));
2145 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, 2145 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2146 sizeof(tcp_ses->dstaddr)); 2146 sizeof(tcp_ses->dstaddr));
2147#ifdef CONFIG_CIFS_SMB2
2148 get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE);
2149#endif
2147 /* 2150 /*
2148 * at this point we are the only ones with the pointer 2151 * at this point we are the only ones with the pointer
2149 * to the struct since the kernel thread not created yet 2152 * to the struct since the kernel thread not created yet
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 3802f8c94acc..dc44610fdc0d 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -375,7 +375,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
375 375
376 req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); 376 req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities);
377 377
378 memcpy(req->ClientGUID, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); 378 memcpy(req->ClientGUID, server->client_guid, SMB2_CLIENT_GUID_SIZE);
379 379
380 iov[0].iov_base = (char *)req; 380 iov[0].iov_base = (char *)req;
381 /* 4 for rfc1002 length field */ 381 /* 4 for rfc1002 length field */
@@ -478,7 +478,8 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
478 478
479 vneg_inbuf.Capabilities = 479 vneg_inbuf.Capabilities =
480 cpu_to_le32(tcon->ses->server->vals->req_capabilities); 480 cpu_to_le32(tcon->ses->server->vals->req_capabilities);
481 memcpy(vneg_inbuf.Guid, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); 481 memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
482 SMB2_CLIENT_GUID_SIZE);
482 483
483 if (tcon->ses->sign) 484 if (tcon->ses->sign)
484 vneg_inbuf.SecurityMode = 485 vneg_inbuf.SecurityMode =
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 2022c542ea3a..743e11e20c5c 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -183,8 +183,6 @@ struct smb2_symlink_err_rsp {
183 183
184#define SMB2_CLIENT_GUID_SIZE 16 184#define SMB2_CLIENT_GUID_SIZE 16
185 185
186extern __u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
187
188struct smb2_negotiate_req { 186struct smb2_negotiate_req {
189 struct smb2_hdr hdr; 187 struct smb2_hdr hdr;
190 __le16 StructureSize; /* Must be 36 */ 188 __le16 StructureSize; /* Must be 36 */