History

cifs: Fix infinite loop when using hard mount option

For every request we send, whether it is SMB1 or SMB2+, we attempt to reconnect tcon (cifs_reconnect_tcon or smb2_reconnect) before carrying out the request. So, while server->tcpStatus != CifsNeedReconnect, we wait for the reconnection to succeed on wait_event_interruptible_timeout(). If it returns, that means that either the condition was evaluated to true, or timeout elapsed, or it was interrupted by a signal. Since we're not handling the case where the process woke up due to a received signal (-ERESTARTSYS), the next call to wait_event_interruptible_timeout() will _always_ fail and we end up looping forever inside either cifs_reconnect_tcon() or smb2_reconnect(). Here's an example of how to trigger that: $ mount.cifs //foo/share /mnt/test -o username=foo,password=foo,vers=1.0,hard (break connection to server before executing bellow cmd) $ stat -f /mnt/test & sleep 140 [1] 2511 $ ps -aux -q 2511 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2511 0.0 0.0 12892 1008 pts/0 S 12:24 0:00 stat -f /mnt/test $ kill -9 2511 (wait for a while; process is stuck in the kernel) $ ps -aux -q 2511 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2511 83.2 0.0 12892 1008 pts/0 R 12:24 30:01 stat -f /mnt/test By using 'hard' mount point means that cifs.ko will keep retrying indefinitely, however we must allow the process to be killed otherwise it would hang the system.

Paulo Alcantara committed 8 years ago

Commit 7ffbe651 parent f46ecbd2 files · +20 −8Browse files

Unified · Split

2 files
  1. fs/cifs/cifssmb.c +8 −2
  2. fs/cifs/smb2pdu.c +12 −6
fs/cifs/cifssmb.c+8−2
@@ -157,8 +157,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) · 156 unmodified lines
157 * greater than cifs socket timeout which is 7 seconds157 * greater than cifs socket timeout which is 7 seconds
158 */158 */
159 while (server->tcpStatus == CifsNeedReconnect) {159 while (server->tcpStatus == CifsNeedReconnect) {
160 wait_event_interruptible_timeout(server->response_q,160 rc = wait_event_interruptible_timeout(server->response_q,
161 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);161 (server->tcpStatus != CifsNeedReconnect),
162 10 * HZ);
163 if (rc < 0) {
164 cifs_dbg(FYI, "%s: aborting reconnect due to a received"
165 " signal by the process\n", __func__);
166 return -ERESTARTSYS;
167 }
162 168
163 /* are we still trying to reconnect? */169 /* are we still trying to reconnect? */
164 if (server->tcpStatus != CifsNeedReconnect)170 if (server->tcpStatus != CifsNeedReconnect)
fs/cifs/smb2pdu.c+12−6
@@ -155,7 +155,7 @@ out: · 154 unmodified lines
155static int155static int
156smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)156smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
157{157{
158 int rc = 0;158 int rc;
159 struct nls_table *nls_codepage;159 struct nls_table *nls_codepage;
160 struct cifs_ses *ses;160 struct cifs_ses *ses;
161 struct TCP_Server_Info *server;161 struct TCP_Server_Info *server;
@@ -166,10 +166,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 4 unmodified lines
166 * for those three - in the calling routine.166 * for those three - in the calling routine.
167 */167 */
168 if (tcon == NULL)168 if (tcon == NULL)
169 return rc;169 return 0;
170 170
171 if (smb2_command == SMB2_TREE_CONNECT)171 if (smb2_command == SMB2_TREE_CONNECT)
172 return rc;172 return 0;
173 173
174 if (tcon->tidStatus == CifsExiting) {174 if (tcon->tidStatus == CifsExiting) {
175 /*175 /*
@@ -212,8 +212,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 36 unmodified lines
212 return -EAGAIN;212 return -EAGAIN;
213 }213 }
214 214
215 wait_event_interruptible_timeout(server->response_q,215 rc = wait_event_interruptible_timeout(server->response_q,
216 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);216 (server->tcpStatus != CifsNeedReconnect),
217 10 * HZ);
218 if (rc < 0) {
219 cifs_dbg(FYI, "%s: aborting reconnect due to a received"
220 " signal by the process\n", __func__);
221 return -ERESTARTSYS;
222 }
217 223
218 /* are we still trying to reconnect? */224 /* are we still trying to reconnect? */
219 if (server->tcpStatus != CifsNeedReconnect)225 if (server->tcpStatus != CifsNeedReconnect)
@@ -231,7 +237,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 11 unmodified lines
231 }237 }
232 238
233 if (!tcon->ses->need_reconnect && !tcon->need_reconnect)239 if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
234 return rc;240 return 0;
235 241
236 nls_codepage = load_nls_default();242 nls_codepage = load_nls_default();
237 243

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t