]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 28 Jan 2019 10:15:30 +0000 (11:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 28 Jan 2019 10:15:30 +0000 (11:15 +0100)
added patches:
cifs-do-not-reconnect-tcp-session-in-add_credits.patch
cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch

queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch [new file with mode: 0644]
queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch b/queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch
new file mode 100644 (file)
index 0000000..cd5bd58
--- /dev/null
@@ -0,0 +1,145 @@
+From ef68e831840c40c7d01b328b3c0f5d8c4796c232 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Fri, 18 Jan 2019 17:25:36 -0800
+Subject: CIFS: Do not reconnect TCP session in add_credits()
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit ef68e831840c40c7d01b328b3c0f5d8c4796c232 upstream.
+
+When executing add_credits() we currently call cifs_reconnect()
+if the number of credits is zero and there are no requests in
+flight. In this case we may call cifs_reconnect() recursively
+twice and cause memory corruption given the following sequence
+of functions:
+
+mid1.callback() -> add_credits() -> cifs_reconnect() ->
+-> mid2.callback() -> add_credits() -> cifs_reconnect().
+
+Fix this by avoiding to call cifs_reconnect() in add_credits()
+and checking for zero credits in the demultiplex thread.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/connect.c |   21 +++++++++++++++++++++
+ fs/cifs/smb2ops.c |   32 +++++++++++++++++++++++++-------
+ 2 files changed, 46 insertions(+), 7 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -518,6 +518,21 @@ server_unresponsive(struct TCP_Server_In
+       return false;
+ }
++static inline bool
++zero_credits(struct TCP_Server_Info *server)
++{
++      int val;
++
++      spin_lock(&server->req_lock);
++      val = server->credits + server->echo_credits + server->oplock_credits;
++      if (server->in_flight == 0 && val == 0) {
++              spin_unlock(&server->req_lock);
++              return true;
++      }
++      spin_unlock(&server->req_lock);
++      return false;
++}
++
+ static int
+ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
+ {
+@@ -530,6 +545,12 @@ cifs_readv_from_socket(struct TCP_Server
+       for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
+               try_to_freeze();
++              /* reconnect if no credits and no requests in flight */
++              if (zero_credits(server)) {
++                      cifs_reconnect(server);
++                      return -ECONNABORTED;
++              }
++
+               if (server_unresponsive(server))
+                       return -ECONNABORTED;
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -30,6 +30,7 @@
+ #include "smb2glob.h"
+ #include "cifs_ioctl.h"
++/* Change credits for different ops and return the total number of credits */
+ static int
+ change_conf(struct TCP_Server_Info *server)
+ {
+@@ -37,17 +38,15 @@ change_conf(struct TCP_Server_Info *serv
+       server->oplock_credits = server->echo_credits = 0;
+       switch (server->credits) {
+       case 0:
+-              return -1;
++              return 0;
+       case 1:
+               server->echoes = false;
+               server->oplocks = false;
+-              cifs_dbg(VFS, "disabling echoes and oplocks\n");
+               break;
+       case 2:
+               server->echoes = true;
+               server->oplocks = false;
+               server->echo_credits = 1;
+-              cifs_dbg(FYI, "disabling oplocks\n");
+               break;
+       default:
+               server->echoes = true;
+@@ -60,14 +59,15 @@ change_conf(struct TCP_Server_Info *serv
+               server->echo_credits = 1;
+       }
+       server->credits -= server->echo_credits + server->oplock_credits;
+-      return 0;
++      return server->credits + server->echo_credits + server->oplock_credits;
+ }
+ static void
+ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
+                const int optype)
+ {
+-      int *val, rc = 0;
++      int *val, rc = -1;
++
+       spin_lock(&server->req_lock);
+       val = server->ops->get_credits_field(server, optype);
+       *val += add;
+@@ -91,8 +91,26 @@ smb2_add_credits(struct TCP_Server_Info
+       }
+       spin_unlock(&server->req_lock);
+       wake_up(&server->request_q);
+-      if (rc)
+-              cifs_reconnect(server);
++
++      if (server->tcpStatus == CifsNeedReconnect)
++              return;
++
++      switch (rc) {
++      case -1:
++              /* change_conf hasn't been executed */
++              break;
++      case 0:
++              cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
++              break;
++      case 1:
++              cifs_dbg(VFS, "disabling echoes and oplocks\n");
++              break;
++      case 2:
++              cifs_dbg(FYI, "disabling oplocks\n");
++              break;
++      default:
++              cifs_dbg(FYI, "add %u credits total=%d\n", add, rc);
++      }
+ }
+ static void
diff --git a/queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch b/queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch
new file mode 100644 (file)
index 0000000..e29b729
--- /dev/null
@@ -0,0 +1,55 @@
+From acc58d0bab55a50e02c25f00bd6a210ee121595f Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Thu, 17 Jan 2019 08:21:24 -0800
+Subject: CIFS: Fix possible hang during async MTU reads and writes
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit acc58d0bab55a50e02c25f00bd6a210ee121595f upstream.
+
+When doing MTU i/o we need to leave some credits for
+possible reopen requests and other operations happening
+in parallel. Currently we leave 1 credit which is not
+enough even for reopen only: we need at least 2 credits
+if durable handle reconnect fails. Also there may be
+other operations at the same time including compounding
+ones which require 3 credits at a time each. Fix this
+by leaving 8 credits which is big enough to cover most
+scenarios.
+
+Was able to reproduce this when server was configured
+to give out fewer credits than usual.
+
+The proper fix would be to reconnect a file handle first
+and then obtain credits for an MTU request but this leads
+to bigger code changes and should happen in other patches.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -148,14 +148,14 @@ smb2_wait_mtu_credits(struct TCP_Server_
+                       scredits = server->credits;
+                       /* can deadlock with reopen */
+-                      if (scredits == 1) {
++                      if (scredits <= 8) {
+                               *num = SMB2_MAX_BUFFER_SIZE;
+                               *credits = 0;
+                               break;
+                       }
+-                      /* leave one credit for a possible reopen */
+-                      scredits--;
++                      /* leave some credits for reopen and other ops */
++                      scredits -= 8;
+                       *num = min_t(unsigned int, size,
+                                    scredits * SMB2_MAX_BUFFER_SIZE);
index 4fb31e1285791f573b47203138fc867d198e8908..1faee3dd4e6162b36698fba6ad3a5b5718e2fe69 100644 (file)
@@ -19,3 +19,5 @@ staging-rtl8188eu-add-device-code-for-d-link-dwa-121-rev-b1.patch
 tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch
 uart-fix-crash-in-uart_write-and-uart_put_char.patch
 tty-n_hdlc-fix-__might_sleep-warning.patch
+cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch
+cifs-do-not-reconnect-tcp-session-in-add_credits.patch