]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Oct 2014 23:48:25 +0000 (16:48 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Oct 2014 23:48:25 +0000 (16:48 -0700)
added patches:
nfsv4-fix-another-bug-in-the-close-open_downgrade-code.patch
nfsv4-nfs4_state_manager-vs.-nfs_server_remove_lists.patch

queue-3.10/nfsv4-fix-another-bug-in-the-close-open_downgrade-code.patch [new file with mode: 0644]
queue-3.10/nfsv4-nfs4_state_manager-vs.-nfs_server_remove_lists.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/nfsv4-fix-another-bug-in-the-close-open_downgrade-code.patch b/queue-3.10/nfsv4-fix-another-bug-in-the-close-open_downgrade-code.patch
new file mode 100644 (file)
index 0000000..2a6230e
--- /dev/null
@@ -0,0 +1,65 @@
+From cd9288ffaea4359d5cfe2b8d264911506aed26a4 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Thu, 18 Sep 2014 11:51:32 -0400
+Subject: NFSv4: Fix another bug in the close/open_downgrade code
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit cd9288ffaea4359d5cfe2b8d264911506aed26a4 upstream.
+
+James Drew reports another bug whereby the NFS client is now sending
+an OPEN_DOWNGRADE in a situation where it should really have sent a
+CLOSE: the client is opening the file for O_RDWR, but then trying to
+do a downgrade to O_RDONLY, which is not allowed by the NFSv4 spec.
+
+Reported-by: James Drews <drews@engr.wisc.edu>
+Link: http://lkml.kernel.org/r/541AD7E5.8020409@engr.wisc.edu
+Fixes: aee7af356e15 (NFSv4: Fix problems with close in the presence...)
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |   30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2299,23 +2299,23 @@ static void nfs4_close_prepare(struct rp
+       is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
+       is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
+       is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
+-      /* Calculate the current open share mode */
+-      calldata->arg.fmode = 0;
+-      if (is_rdonly || is_rdwr)
+-              calldata->arg.fmode |= FMODE_READ;
+-      if (is_wronly || is_rdwr)
+-              calldata->arg.fmode |= FMODE_WRITE;
+       /* Calculate the change in open mode */
++      calldata->arg.fmode = 0;
+       if (state->n_rdwr == 0) {
+-              if (state->n_rdonly == 0) {
+-                      call_close |= is_rdonly || is_rdwr;
+-                      calldata->arg.fmode &= ~FMODE_READ;
+-              }
+-              if (state->n_wronly == 0) {
+-                      call_close |= is_wronly || is_rdwr;
+-                      calldata->arg.fmode &= ~FMODE_WRITE;
+-              }
+-      }
++              if (state->n_rdonly == 0)
++                      call_close |= is_rdonly;
++              else if (is_rdonly)
++                      calldata->arg.fmode |= FMODE_READ;
++              if (state->n_wronly == 0)
++                      call_close |= is_wronly;
++              else if (is_wronly)
++                      calldata->arg.fmode |= FMODE_WRITE;
++      } else if (is_rdwr)
++              calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
++
++      if (calldata->arg.fmode == 0)
++              call_close |= is_rdwr;
++
+       if (!nfs4_valid_open_stateid(state))
+               call_close = 0;
+       spin_unlock(&state->owner->so_lock);
diff --git a/queue-3.10/nfsv4-nfs4_state_manager-vs.-nfs_server_remove_lists.patch b/queue-3.10/nfsv4-nfs4_state_manager-vs.-nfs_server_remove_lists.patch
new file mode 100644 (file)
index 0000000..3421cab
--- /dev/null
@@ -0,0 +1,101 @@
+From 080af20cc945d110f9912d01cf6b66f94a375b8d Mon Sep 17 00:00:00 2001
+From: Steve Dickson <steved@redhat.com>
+Date: Thu, 18 Sep 2014 09:13:17 -0400
+Subject: NFSv4: nfs4_state_manager() vs. nfs_server_remove_lists()
+
+From: Steve Dickson <steved@redhat.com>
+
+commit 080af20cc945d110f9912d01cf6b66f94a375b8d upstream.
+
+There is a race between nfs4_state_manager() and
+nfs_server_remove_lists() that happens during a nfsv3 mount.
+
+The v3 mount notices there is already a supper block so
+nfs_server_remove_lists() called which uses the nfs_client_lock
+spin lock to synchronize access to the client list.
+
+At the same time nfs4_state_manager() is running through
+the client list looking for work to do, using the same
+lock. When nfs4_state_manager() wins the race to the
+list, a v3 client pointer is found and not ignored
+properly which causes the panic.
+
+Moving some protocol checks before the state checking
+avoids the panic.
+
+Signed-off-by: Steve Dickson <steved@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4client.c |   38 ++++++++++++++++++++------------------
+ 1 file changed, 20 insertions(+), 18 deletions(-)
+
+--- a/fs/nfs/nfs4client.c
++++ b/fs/nfs/nfs4client.c
+@@ -311,6 +311,16 @@ int nfs40_walk_client_list(struct nfs_cl
+       spin_lock(&nn->nfs_client_lock);
+       list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
++
++              if (pos->rpc_ops != new->rpc_ops)
++                      continue;
++
++              if (pos->cl_proto != new->cl_proto)
++                      continue;
++
++              if (pos->cl_minorversion != new->cl_minorversion)
++                      continue;
++
+               /* If "pos" isn't marked ready, we can't trust the
+                * remaining fields in "pos" */
+               if (pos->cl_cons_state > NFS_CS_READY) {
+@@ -330,15 +340,6 @@ int nfs40_walk_client_list(struct nfs_cl
+               if (pos->cl_cons_state != NFS_CS_READY)
+                       continue;
+-              if (pos->rpc_ops != new->rpc_ops)
+-                      continue;
+-
+-              if (pos->cl_proto != new->cl_proto)
+-                      continue;
+-
+-              if (pos->cl_minorversion != new->cl_minorversion)
+-                      continue;
+-
+               if (pos->cl_clientid != new->cl_clientid)
+                       continue;
+@@ -444,6 +445,16 @@ int nfs41_walk_client_list(struct nfs_cl
+       spin_lock(&nn->nfs_client_lock);
+       list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
++
++              if (pos->rpc_ops != new->rpc_ops)
++                      continue;
++
++              if (pos->cl_proto != new->cl_proto)
++                      continue;
++
++              if (pos->cl_minorversion != new->cl_minorversion)
++                      continue;
++
+               /* If "pos" isn't marked ready, we can't trust the
+                * remaining fields in "pos", especially the client
+                * ID and serverowner fields.  Wait for CREATE_SESSION
+@@ -469,15 +480,6 @@ int nfs41_walk_client_list(struct nfs_cl
+               if (pos->cl_cons_state != NFS_CS_READY)
+                       continue;
+-              if (pos->rpc_ops != new->rpc_ops)
+-                      continue;
+-
+-              if (pos->cl_proto != new->cl_proto)
+-                      continue;
+-
+-              if (pos->cl_minorversion != new->cl_minorversion)
+-                      continue;
+-
+               if (!nfs4_match_clientids(pos, new))
+                       continue;
index b53b7c37977bb5931568c58cb99e451e6109cd0c..385cfc1f5c027f05d1d115e08b798c59512d0605 100644 (file)
@@ -59,3 +59,5 @@ usb-storage-add-quirks-for-entrega-xircom-usb-to-scsi-converters.patch
 usb-ehci-unlink-qhs-even-after-the-controller-has-stopped.patch
 usb-dwc3-omap-fix-ordering-for-runtime-pm-calls.patch
 usb-hub-set-hub-change_bits-when-over-current-happens.patch
+nfsv4-nfs4_state_manager-vs.-nfs_server_remove_lists.patch
+nfsv4-fix-another-bug-in-the-close-open_downgrade-code.patch