Skip to content

Commit 02002e1

Browse files
piastrysamueldr
authored andcommitted
CIFS: Reconnect expired SMB sessions
commit 511c54a 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 7c37a5f commit 02002e1

File tree

4 files changed

+31
-0
lines changed

4 files changed

+31
-0
lines changed

fs/cifs/cifsglob.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ struct smb_version_operations {
347347
unsigned int (*calc_smb_size)(void *);
348348
/* check for STATUS_PENDING and process it in a positive case */
349349
bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
350+
/* check for STATUS_NETWORK_SESSION_EXPIRED */
351+
bool (*is_session_expired)(char *);
350352
/* send oplock break response */
351353
int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
352354
struct cifsInodeInfo *);

fs/cifs/cifssmb.c

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

1461+
if (server->ops->is_session_expired &&
1462+
server->ops->is_session_expired(buf)) {
1463+
cifs_reconnect(server);
1464+
wake_up(&server->response_q);
1465+
return -1;
1466+
}
1467+
14611468
if (server->ops->is_status_pending &&
14621469
server->ops->is_status_pending(buf, server, 0)) {
14631470
discard_remaining_data(server);

fs/cifs/connect.c

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

842+
if (server->ops->is_session_expired &&
843+
server->ops->is_session_expired(buf)) {
844+
cifs_reconnect(server);
845+
wake_up(&server->response_q);
846+
return -1;
847+
}
848+
842849
if (server->ops->is_status_pending &&
843850
server->ops->is_status_pending(buf, server, length))
844851
return -1;

fs/cifs/smb2ops.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,18 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
896896
return true;
897897
}
898898

899+
static bool
900+
smb2_is_session_expired(char *buf)
901+
{
902+
struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
903+
904+
if (hdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
905+
return false;
906+
907+
cifs_dbg(FYI, "Session expired\n");
908+
return true;
909+
}
910+
899911
static int
900912
smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
901913
struct cifsInodeInfo *cinode)
@@ -1424,6 +1436,7 @@ struct smb_version_operations smb20_operations = {
14241436
.close_dir = smb2_close_dir,
14251437
.calc_smb_size = smb2_calc_size,
14261438
.is_status_pending = smb2_is_status_pending,
1439+
.is_session_expired = smb2_is_session_expired,
14271440
.oplock_response = smb2_oplock_response,
14281441
.queryfs = smb2_queryfs,
14291442
.mand_lock = smb2_mand_lock,
@@ -1505,6 +1518,7 @@ struct smb_version_operations smb21_operations = {
15051518
.close_dir = smb2_close_dir,
15061519
.calc_smb_size = smb2_calc_size,
15071520
.is_status_pending = smb2_is_status_pending,
1521+
.is_session_expired = smb2_is_session_expired,
15081522
.oplock_response = smb2_oplock_response,
15091523
.queryfs = smb2_queryfs,
15101524
.mand_lock = smb2_mand_lock,
@@ -1587,6 +1601,7 @@ struct smb_version_operations smb30_operations = {
15871601
.close_dir = smb2_close_dir,
15881602
.calc_smb_size = smb2_calc_size,
15891603
.is_status_pending = smb2_is_status_pending,
1604+
.is_session_expired = smb2_is_session_expired,
15901605
.oplock_response = smb2_oplock_response,
15911606
.queryfs = smb2_queryfs,
15921607
.mand_lock = smb2_mand_lock,

0 commit comments

Comments
 (0)