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
157157 * greater than cifs socket timeout which is 7 seconds
158158 */
159159 while (server->tcpStatus == CifsNeedReconnect) {
160− wait_event_interruptible_timeout(server->response_q,
161− (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
160+ rc = wait_event_interruptible_timeout(server->response_q,
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+ }
162168
163169 /* are we still trying to reconnect? */
164170 if (server->tcpStatus != CifsNeedReconnect)
fs/cifs/smb2pdu.c+12−6
@@ -155,7 +155,7 @@ out: · 154 unmodified lines
155155 static int
156156 smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
157157 {
158− int rc = 0;
158+ int rc;
159159 struct nls_table *nls_codepage;
160160 struct cifs_ses *ses;
161161 struct TCP_Server_Info *server;
@@ -166,10 +166,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 4 unmodified lines
166166 * for those three - in the calling routine.
167167 */
168168 if (tcon == NULL)
169− return rc;
169+ return 0;
170170
171171 if (smb2_command == SMB2_TREE_CONNECT)
172− return rc;
172+ return 0;
173173
174174 if (tcon->tidStatus == CifsExiting) {
175175 /*
@@ -212,8 +212,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 36 unmodified lines
212212 return -EAGAIN;
213213 }
214214
215− wait_event_interruptible_timeout(server->response_q,
216− (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
215+ rc = wait_event_interruptible_timeout(server->response_q,
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+ }
217223
218224 /* are we still trying to reconnect? */
219225 if (server->tcpStatus != CifsNeedReconnect)
@@ -231,7 +237,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 11 unmodified lines
231237 }
232238
233239 if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
234− return rc;
240+ return 0;
235241
236242 nls_codepage = load_nls_default();
237243

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