]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.4.140/cifs-fix-infinite-loop-when-using-hard-mount-option.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.4.140 / cifs-fix-infinite-loop-when-using-hard-mount-option.patch
1 From 7ffbe65578b44fafdef577a360eb0583929f7c6e Mon Sep 17 00:00:00 2001
2 From: Paulo Alcantara <paulo@paulo.ac>
3 Date: Thu, 5 Jul 2018 13:46:34 -0300
4 Subject: cifs: Fix infinite loop when using hard mount option
5
6 From: Paulo Alcantara <paulo@paulo.ac>
7
8 commit 7ffbe65578b44fafdef577a360eb0583929f7c6e upstream.
9
10 For every request we send, whether it is SMB1 or SMB2+, we attempt to
11 reconnect tcon (cifs_reconnect_tcon or smb2_reconnect) before carrying
12 out the request.
13
14 So, while server->tcpStatus != CifsNeedReconnect, we wait for the
15 reconnection to succeed on wait_event_interruptible_timeout(). If it
16 returns, that means that either the condition was evaluated to true, or
17 timeout elapsed, or it was interrupted by a signal.
18
19 Since we're not handling the case where the process woke up due to a
20 received signal (-ERESTARTSYS), the next call to
21 wait_event_interruptible_timeout() will _always_ fail and we end up
22 looping forever inside either cifs_reconnect_tcon() or smb2_reconnect().
23
24 Here's an example of how to trigger that:
25
26 $ mount.cifs //foo/share /mnt/test -o
27 username=foo,password=foo,vers=1.0,hard
28
29 (break connection to server before executing bellow cmd)
30 $ stat -f /mnt/test & sleep 140
31 [1] 2511
32
33 $ ps -aux -q 2511
34 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
35 root 2511 0.0 0.0 12892 1008 pts/0 S 12:24 0:00 stat -f
36 /mnt/test
37
38 $ kill -9 2511
39
40 (wait for a while; process is stuck in the kernel)
41 $ ps -aux -q 2511
42 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
43 root 2511 83.2 0.0 12892 1008 pts/0 R 12:24 30:01 stat -f
44 /mnt/test
45
46 By using 'hard' mount point means that cifs.ko will keep retrying
47 indefinitely, however we must allow the process to be killed otherwise
48 it would hang the system.
49
50 Signed-off-by: Paulo Alcantara <palcantara@suse.de>
51 Cc: stable@vger.kernel.org
52 Reviewed-by: Aurelien Aptel <aaptel@suse.com>
53 Signed-off-by: Steve French <stfrench@microsoft.com>
54 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
55
56 ---
57 fs/cifs/cifssmb.c | 10 ++++++++--
58 fs/cifs/smb2pdu.c | 18 ++++++++++++------
59 2 files changed, 20 insertions(+), 8 deletions(-)
60
61 --- a/fs/cifs/cifssmb.c
62 +++ b/fs/cifs/cifssmb.c
63 @@ -150,8 +150,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tc
64 * greater than cifs socket timeout which is 7 seconds
65 */
66 while (server->tcpStatus == CifsNeedReconnect) {
67 - wait_event_interruptible_timeout(server->response_q,
68 - (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
69 + rc = wait_event_interruptible_timeout(server->response_q,
70 + (server->tcpStatus != CifsNeedReconnect),
71 + 10 * HZ);
72 + if (rc < 0) {
73 + cifs_dbg(FYI, "%s: aborting reconnect due to a received"
74 + " signal by the process\n", __func__);
75 + return -ERESTARTSYS;
76 + }
77
78 /* are we still trying to reconnect? */
79 if (server->tcpStatus != CifsNeedReconnect)
80 --- a/fs/cifs/smb2pdu.c
81 +++ b/fs/cifs/smb2pdu.c
82 @@ -158,7 +158,7 @@ out:
83 static int
84 smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
85 {
86 - int rc = 0;
87 + int rc;
88 struct nls_table *nls_codepage;
89 struct cifs_ses *ses;
90 struct TCP_Server_Info *server;
91 @@ -169,10 +169,10 @@ smb2_reconnect(__le16 smb2_command, stru
92 * for those three - in the calling routine.
93 */
94 if (tcon == NULL)
95 - return rc;
96 + return 0;
97
98 if (smb2_command == SMB2_TREE_CONNECT)
99 - return rc;
100 + return 0;
101
102 if (tcon->tidStatus == CifsExiting) {
103 /*
104 @@ -215,8 +215,14 @@ smb2_reconnect(__le16 smb2_command, stru
105 return -EAGAIN;
106 }
107
108 - wait_event_interruptible_timeout(server->response_q,
109 - (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
110 + rc = wait_event_interruptible_timeout(server->response_q,
111 + (server->tcpStatus != CifsNeedReconnect),
112 + 10 * HZ);
113 + if (rc < 0) {
114 + cifs_dbg(FYI, "%s: aborting reconnect due to a received"
115 + " signal by the process\n", __func__);
116 + return -ERESTARTSYS;
117 + }
118
119 /* are we still trying to reconnect? */
120 if (server->tcpStatus != CifsNeedReconnect)
121 @@ -234,7 +240,7 @@ smb2_reconnect(__le16 smb2_command, stru
122 }
123
124 if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
125 - return rc;
126 + return 0;
127
128 nls_codepage = load_nls_default();
129