]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.4.93/cifs-reconnect-expired-smb-sessions.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.4.93 / cifs-reconnect-expired-smb-sessions.patch
CommitLineData
67307134
GKH
1From 511c54a2f69195b28afb9dd119f03787b1625bb4 Mon Sep 17 00:00:00 2001
2From: Pavel Shilovsky <pshilov@microsoft.com>
3Date: Sat, 8 Jul 2017 14:32:00 -0700
4Subject: CIFS: Reconnect expired SMB sessions
5
6From: Pavel Shilovsky <pshilov@microsoft.com>
7
8commit 511c54a2f69195b28afb9dd119f03787b1625bb4 upstream.
9
10According to the MS-SMB2 spec (3.2.5.1.6) once the client receives
11STATUS_NETWORK_SESSION_EXPIRED error code from a server it should
12reconnect the current SMB session. Currently the client doesn't do
13that. This can result in subsequent client requests failing by
14the server. The patch adds an additional logic to the demultiplex
15thread to identify expired sessions and reconnect them.
16
17Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
18Signed-off-by: Steve French <smfrench@gmail.com>
19Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20
21---
22 fs/cifs/cifsglob.h | 2 ++
23 fs/cifs/cifssmb.c | 7 +++++++
24 fs/cifs/connect.c | 7 +++++++
25 fs/cifs/smb2ops.c | 16 ++++++++++++++++
26 4 files changed, 32 insertions(+)
27
28--- a/fs/cifs/cifsglob.h
29+++ b/fs/cifs/cifsglob.h
30@@ -351,6 +351,8 @@ struct smb_version_operations {
31 unsigned int (*calc_smb_size)(void *);
32 /* check for STATUS_PENDING and process it in a positive case */
33 bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
34+ /* check for STATUS_NETWORK_SESSION_EXPIRED */
35+ bool (*is_session_expired)(char *);
36 /* send oplock break response */
37 int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
38 struct cifsInodeInfo *);
39--- a/fs/cifs/cifssmb.c
40+++ b/fs/cifs/cifssmb.c
41@@ -1460,6 +1460,13 @@ cifs_readv_receive(struct TCP_Server_Inf
42 return length;
43 server->total_read += length;
44
45+ if (server->ops->is_session_expired &&
46+ server->ops->is_session_expired(buf)) {
47+ cifs_reconnect(server);
48+ wake_up(&server->response_q);
49+ return -1;
50+ }
51+
52 if (server->ops->is_status_pending &&
53 server->ops->is_status_pending(buf, server, 0)) {
54 discard_remaining_data(server);
55--- a/fs/cifs/connect.c
56+++ b/fs/cifs/connect.c
57@@ -850,6 +850,13 @@ standard_receive3(struct TCP_Server_Info
58 cifs_dump_mem("Bad SMB: ", buf,
59 min_t(unsigned int, server->total_read, 48));
60
61+ if (server->ops->is_session_expired &&
62+ server->ops->is_session_expired(buf)) {
63+ cifs_reconnect(server);
64+ wake_up(&server->response_q);
65+ return -1;
66+ }
67+
68 if (server->ops->is_status_pending &&
69 server->ops->is_status_pending(buf, server, length))
70 return -1;
71--- a/fs/cifs/smb2ops.c
72+++ b/fs/cifs/smb2ops.c
73@@ -963,6 +963,18 @@ smb2_is_status_pending(char *buf, struct
74 return true;
75 }
76
77+static bool
78+smb2_is_session_expired(char *buf)
79+{
80+ struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
81+
82+ if (hdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
83+ return false;
84+
85+ cifs_dbg(FYI, "Session expired\n");
86+ return true;
87+}
88+
89 static int
90 smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
91 struct cifsInodeInfo *cinode)
92@@ -1552,6 +1564,7 @@ struct smb_version_operations smb20_oper
93 .close_dir = smb2_close_dir,
94 .calc_smb_size = smb2_calc_size,
95 .is_status_pending = smb2_is_status_pending,
96+ .is_session_expired = smb2_is_session_expired,
97 .oplock_response = smb2_oplock_response,
98 .queryfs = smb2_queryfs,
99 .mand_lock = smb2_mand_lock,
100@@ -1633,6 +1646,7 @@ struct smb_version_operations smb21_oper
101 .close_dir = smb2_close_dir,
102 .calc_smb_size = smb2_calc_size,
103 .is_status_pending = smb2_is_status_pending,
104+ .is_session_expired = smb2_is_session_expired,
105 .oplock_response = smb2_oplock_response,
106 .queryfs = smb2_queryfs,
107 .mand_lock = smb2_mand_lock,
108@@ -1715,6 +1729,7 @@ struct smb_version_operations smb30_oper
109 .close_dir = smb2_close_dir,
110 .calc_smb_size = smb2_calc_size,
111 .is_status_pending = smb2_is_status_pending,
112+ .is_session_expired = smb2_is_session_expired,
113 .oplock_response = smb2_oplock_response,
114 .queryfs = smb2_queryfs,
115 .mand_lock = smb2_mand_lock,
116@@ -1803,6 +1818,7 @@ struct smb_version_operations smb311_ope
117 .close_dir = smb2_close_dir,
118 .calc_smb_size = smb2_calc_size,
119 .is_status_pending = smb2_is_status_pending,
120+ .is_session_expired = smb2_is_session_expired,
121 .oplock_response = smb2_oplock_response,
122 .queryfs = smb2_queryfs,
123 .mand_lock = smb2_mand_lock,