Skip to content

Commit f2bb4bc

Browse files
piastrygregkh
authored andcommitted
CIFS: Reconnect expired SMB sessions
commit 511c54a2f69195b28afb9dd119f03787b1625bb4 upstream. According to the MS-SMB2 spec (3.2.5.1.6) once the client receives STATUS_NETWORK_SESSION_EXPIRED error code from a server it should reconnect the current SMB session. Currently the client doesn't do that. This can result in subsequent client requests failing by the server. The patch adds an additional logic to the demultiplex thread to identify expired sessions and reconnect them. Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Signed-off-by: Steve French <smfrench@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent bd36826 commit f2bb4bc

4 files changed

Lines changed: 32 additions & 0 deletions

File tree

fs/cifs/cifsglob.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ struct smb_version_operations {
351351
unsigned int (*calc_smb_size)(void *);
352352
/* check for STATUS_PENDING and process it in a positive case */
353353
bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
354+
/* check for STATUS_NETWORK_SESSION_EXPIRED */
355+
bool (*is_session_expired)(char *);
354356
/* send oplock break response */
355357
int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
356358
struct cifsInodeInfo *);

fs/cifs/cifssmb.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,13 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
14601460
return length;
14611461
server->total_read += length;
14621462

1463+
if (server->ops->is_session_expired &&
1464+
server->ops->is_session_expired(buf)) {
1465+
cifs_reconnect(server);
1466+
wake_up(&server->response_q);
1467+
return -1;
1468+
}
1469+
14631470
if (server->ops->is_status_pending &&
14641471
server->ops->is_status_pending(buf, server, 0)) {
14651472
discard_remaining_data(server);

fs/cifs/connect.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,13 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
850850
cifs_dump_mem("Bad SMB: ", buf,
851851
min_t(unsigned int, server->total_read, 48));
852852

853+
if (server->ops->is_session_expired &&
854+
server->ops->is_session_expired(buf)) {
855+
cifs_reconnect(server);
856+
wake_up(&server->response_q);
857+
return -1;
858+
}
859+
853860
if (server->ops->is_status_pending &&
854861
server->ops->is_status_pending(buf, server, length))
855862
return -1;

fs/cifs/smb2ops.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,18 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
963963
return true;
964964
}
965965

966+
static bool
967+
smb2_is_session_expired(char *buf)
968+
{
969+
struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
970+
971+
if (hdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
972+
return false;
973+
974+
cifs_dbg(FYI, "Session expired\n");
975+
return true;
976+
}
977+
966978
static int
967979
smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
968980
struct cifsInodeInfo *cinode)
@@ -1552,6 +1564,7 @@ struct smb_version_operations smb20_operations = {
15521564
.close_dir = smb2_close_dir,
15531565
.calc_smb_size = smb2_calc_size,
15541566
.is_status_pending = smb2_is_status_pending,
1567+
.is_session_expired = smb2_is_session_expired,
15551568
.oplock_response = smb2_oplock_response,
15561569
.queryfs = smb2_queryfs,
15571570
.mand_lock = smb2_mand_lock,
@@ -1633,6 +1646,7 @@ struct smb_version_operations smb21_operations = {
16331646
.close_dir = smb2_close_dir,
16341647
.calc_smb_size = smb2_calc_size,
16351648
.is_status_pending = smb2_is_status_pending,
1649+
.is_session_expired = smb2_is_session_expired,
16361650
.oplock_response = smb2_oplock_response,
16371651
.queryfs = smb2_queryfs,
16381652
.mand_lock = smb2_mand_lock,
@@ -1715,6 +1729,7 @@ struct smb_version_operations smb30_operations = {
17151729
.close_dir = smb2_close_dir,
17161730
.calc_smb_size = smb2_calc_size,
17171731
.is_status_pending = smb2_is_status_pending,
1732+
.is_session_expired = smb2_is_session_expired,
17181733
.oplock_response = smb2_oplock_response,
17191734
.queryfs = smb2_queryfs,
17201735
.mand_lock = smb2_mand_lock,
@@ -1803,6 +1818,7 @@ struct smb_version_operations smb311_operations = {
18031818
.close_dir = smb2_close_dir,
18041819
.calc_smb_size = smb2_calc_size,
18051820
.is_status_pending = smb2_is_status_pending,
1821+
.is_session_expired = smb2_is_session_expired,
18061822
.oplock_response = smb2_oplock_response,
18071823
.queryfs = smb2_queryfs,
18081824
.mand_lock = smb2_mand_lock,

0 commit comments

Comments
 (0)