]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Sep 2014 15:20:51 +0000 (08:20 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Sep 2014 15:20:51 +0000 (08:20 -0700)
added patches:
blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch
cifs-fix-async-reading-on-reconnects.patch
cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch
cifs-fix-wrong-directory-attributes-after-rename.patch
cifs-fix-wrong-filename-length-for-smb2.patch
cifs-fix-wrong-restart-readdir-for-smb1.patch
cifs-possible-null-ptr-deref-in-smb2_tcon.patch
ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch
libceph-add-process_one_ticket-helper.patch
libceph-do-not-hard-code-max-auth-ticket-len.patch
libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch
mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch
mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch

14 files changed:
queue-3.10/blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch [new file with mode: 0644]
queue-3.10/cifs-fix-async-reading-on-reconnects.patch [new file with mode: 0644]
queue-3.10/cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch [new file with mode: 0644]
queue-3.10/cifs-fix-wrong-directory-attributes-after-rename.patch [new file with mode: 0644]
queue-3.10/cifs-fix-wrong-filename-length-for-smb2.patch [new file with mode: 0644]
queue-3.10/cifs-fix-wrong-restart-readdir-for-smb1.patch [new file with mode: 0644]
queue-3.10/cifs-possible-null-ptr-deref-in-smb2_tcon.patch [new file with mode: 0644]
queue-3.10/ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch [new file with mode: 0644]
queue-3.10/libceph-add-process_one_ticket-helper.patch [new file with mode: 0644]
queue-3.10/libceph-do-not-hard-code-max-auth-ticket-len.patch [new file with mode: 0644]
queue-3.10/libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch [new file with mode: 0644]
queue-3.10/mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch [new file with mode: 0644]
queue-3.10/mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch b/queue-3.10/blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch
new file mode 100644 (file)
index 0000000..7c3df2e
--- /dev/null
@@ -0,0 +1,102 @@
+From 2a1b4cf2331d92bc009bf94fa02a24604cdaf24c Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Sat, 5 Jul 2014 18:43:21 -0400
+Subject: blkcg: don't call into policy draining if root_blkg is already gone
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 2a1b4cf2331d92bc009bf94fa02a24604cdaf24c upstream.
+
+While a queue is being destroyed, all the blkgs are destroyed and its
+->root_blkg pointer is set to NULL.  If someone else starts to drain
+while the queue is in this state, the following oops happens.
+
+  NULL pointer dereference at 0000000000000028
+  IP: [<ffffffff8144e944>] blk_throtl_drain+0x84/0x230
+  PGD e4a1067 PUD b773067 PMD 0
+  Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
+  Modules linked in: cfq_iosched(-) [last unloaded: cfq_iosched]
+  CPU: 1 PID: 537 Comm: bash Not tainted 3.16.0-rc3-work+ #2
+  Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+  task: ffff88000e222250 ti: ffff88000efd4000 task.ti: ffff88000efd4000
+  RIP: 0010:[<ffffffff8144e944>]  [<ffffffff8144e944>] blk_throtl_drain+0x84/0x230
+  RSP: 0018:ffff88000efd7bf0  EFLAGS: 00010046
+  RAX: 0000000000000000 RBX: ffff880015091450 RCX: 0000000000000001
+  RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
+  RBP: ffff88000efd7c10 R08: 0000000000000000 R09: 0000000000000001
+  R10: ffff88000e222250 R11: 0000000000000000 R12: ffff880015091450
+  R13: ffff880015092e00 R14: ffff880015091d70 R15: ffff88001508fc28
+  FS:  00007f1332650740(0000) GS:ffff88001fa80000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+  CR2: 0000000000000028 CR3: 0000000009446000 CR4: 00000000000006e0
+  Stack:
+   ffffffff8144e8f6 ffff880015091450 0000000000000000 ffff880015091d80
+   ffff88000efd7c28 ffffffff8144ae2f ffff880015091450 ffff88000efd7c58
+   ffffffff81427641 ffff880015091450 ffffffff82401f00 ffff880015091450
+  Call Trace:
+   [<ffffffff8144ae2f>] blkcg_drain_queue+0x1f/0x60
+   [<ffffffff81427641>] __blk_drain_queue+0x71/0x180
+   [<ffffffff81429b3e>] blk_queue_bypass_start+0x6e/0xb0
+   [<ffffffff814498b8>] blkcg_deactivate_policy+0x38/0x120
+   [<ffffffff8144ec44>] blk_throtl_exit+0x34/0x50
+   [<ffffffff8144aea5>] blkcg_exit_queue+0x35/0x40
+   [<ffffffff8142d476>] blk_release_queue+0x26/0xd0
+   [<ffffffff81454968>] kobject_cleanup+0x38/0x70
+   [<ffffffff81454848>] kobject_put+0x28/0x60
+   [<ffffffff81427505>] blk_put_queue+0x15/0x20
+   [<ffffffff817d07bb>] scsi_device_dev_release_usercontext+0x16b/0x1c0
+   [<ffffffff810bc339>] execute_in_process_context+0x89/0xa0
+   [<ffffffff817d064c>] scsi_device_dev_release+0x1c/0x20
+   [<ffffffff817930e2>] device_release+0x32/0xa0
+   [<ffffffff81454968>] kobject_cleanup+0x38/0x70
+   [<ffffffff81454848>] kobject_put+0x28/0x60
+   [<ffffffff817934d7>] put_device+0x17/0x20
+   [<ffffffff817d11b9>] __scsi_remove_device+0xa9/0xe0
+   [<ffffffff817d121b>] scsi_remove_device+0x2b/0x40
+   [<ffffffff817d1257>] sdev_store_delete+0x27/0x30
+   [<ffffffff81792ca8>] dev_attr_store+0x18/0x30
+   [<ffffffff8126f75e>] sysfs_kf_write+0x3e/0x50
+   [<ffffffff8126ea87>] kernfs_fop_write+0xe7/0x170
+   [<ffffffff811f5e9f>] vfs_write+0xaf/0x1d0
+   [<ffffffff811f69bd>] SyS_write+0x4d/0xc0
+   [<ffffffff81d24692>] system_call_fastpath+0x16/0x1b
+
+776687bce42b ("block, blk-mq: draining can't be skipped even if
+bypass_depth was non-zero") made it easier to trigger this bug by
+making blk_queue_bypass_start() drain even when it loses the first
+bypass test to blk_cleanup_queue(); however, the bug has always been
+there even before the commit as blk_queue_bypass_start() could race
+against queue destruction, win the initial bypass test but perform the
+actual draining after blk_cleanup_queue() already destroyed all blkgs.
+
+Fix it by skippping calling into policy draining if all the blkgs are
+already gone.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Shirish Pargaonkar <spargaonkar@suse.com>
+Reported-by: Sasha Levin <sasha.levin@oracle.com>
+Reported-by: Jet Chen <jet.chen@intel.com>
+Tested-by: Shirish Pargaonkar <spargaonkar@suse.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/blk-cgroup.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -883,6 +883,13 @@ void blkcg_drain_queue(struct request_qu
+       if (!q->root_blkg)
+               return;
++      /*
++       * @q could be exiting and already have destroyed all blkgs as
++       * indicated by NULL root_blkg.  If so, don't confuse policies.
++       */
++      if (!q->root_blkg)
++              return;
++
+       blk_throtl_drain(q);
+ }
diff --git a/queue-3.10/cifs-fix-async-reading-on-reconnects.patch b/queue-3.10/cifs-fix-async-reading-on-reconnects.patch
new file mode 100644 (file)
index 0000000..89e4629
--- /dev/null
@@ -0,0 +1,51 @@
+From 038bc961c31b070269ecd07349a7ee2e839d4fec Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Fri, 27 Jun 2014 10:33:11 +0400
+Subject: CIFS: Fix async reading on reconnects
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 038bc961c31b070269ecd07349a7ee2e839d4fec upstream.
+
+If we get into read_into_pages() from cifs_readv_receive() and then
+loose a network, we issue cifs_reconnect that moves all mids to
+a private list and issue their callbacks. The callback of the async
+read request sets a mid to retry, frees it and wakes up a process
+that waits on the rdata completion.
+
+After the connection is established we return from read_into_pages()
+with a short read, use the mid that was freed before and try to read
+the remaining data from the a newly created socket. Both actions are
+not what we want to do. In reconnect cases (-EAGAIN) we should not
+mask off the error with a short read but should return the error
+code instead.
+
+Acked-by: Jeff Layton <jlayton@samba.org>
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/file.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -2809,7 +2809,7 @@ cifs_uncached_read_into_pages(struct TCP
+               total_read += result;
+       }
+-      return total_read > 0 ? total_read : result;
++      return total_read > 0 && result != -EAGAIN ? total_read : result;
+ }
+ static ssize_t
+@@ -3232,7 +3232,7 @@ cifs_readpages_read_into_pages(struct TC
+               total_read += result;
+       }
+-      return total_read > 0 ? total_read : result;
++      return total_read > 0 && result != -EAGAIN ? total_read : result;
+ }
+ static int cifs_readpages(struct file *file, struct address_space *mapping,
diff --git a/queue-3.10/cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch b/queue-3.10/cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch
new file mode 100644 (file)
index 0000000..41c89d8
--- /dev/null
@@ -0,0 +1,33 @@
+From 21496687a79424572f46a84c690d331055f4866f Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Fri, 18 Jul 2014 18:25:52 +0400
+Subject: CIFS: Fix STATUS_CANNOT_DELETE error mapping for SMB2
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 21496687a79424572f46a84c690d331055f4866f upstream.
+
+The existing mapping causes unlink() call to return error after delete
+operation. Changing the mapping to -EACCES makes the client process
+the call like CIFS protocol does - reset dos attributes with ATTR_READONLY
+flag masked off and retry the operation.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2maperror.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2maperror.c
++++ b/fs/cifs/smb2maperror.c
+@@ -605,7 +605,7 @@ static const struct status_to_posix_erro
+       {STATUS_MAPPED_FILE_SIZE_ZERO, -EIO, "STATUS_MAPPED_FILE_SIZE_ZERO"},
+       {STATUS_TOO_MANY_OPENED_FILES, -EMFILE, "STATUS_TOO_MANY_OPENED_FILES"},
+       {STATUS_CANCELLED, -EIO, "STATUS_CANCELLED"},
+-      {STATUS_CANNOT_DELETE, -EIO, "STATUS_CANNOT_DELETE"},
++      {STATUS_CANNOT_DELETE, -EACCES, "STATUS_CANNOT_DELETE"},
+       {STATUS_INVALID_COMPUTER_NAME, -EIO, "STATUS_INVALID_COMPUTER_NAME"},
+       {STATUS_FILE_DELETED, -EIO, "STATUS_FILE_DELETED"},
+       {STATUS_SPECIAL_ACCOUNT, -EIO, "STATUS_SPECIAL_ACCOUNT"},
diff --git a/queue-3.10/cifs-fix-wrong-directory-attributes-after-rename.patch b/queue-3.10/cifs-fix-wrong-directory-attributes-after-rename.patch
new file mode 100644 (file)
index 0000000..504d064
--- /dev/null
@@ -0,0 +1,37 @@
+From b46799a8f28c43c5264ac8d8ffa28b311b557e03 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Mon, 18 Aug 2014 20:49:58 +0400
+Subject: CIFS: Fix wrong directory attributes after rename
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit b46799a8f28c43c5264ac8d8ffa28b311b557e03 upstream.
+
+When we requests rename we also need to update attributes
+of both source and target parent directories. Not doing it
+causes generic/309 xfstest to fail on SMB2 mounts. Fix this
+by marking these directories for force revalidating.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/inode.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -1647,6 +1647,12 @@ unlink_target:
+                                   target_dentry, to_name);
+       }
++      /* force revalidate to go get info when needed */
++      CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
++
++      source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
++              target_dir->i_mtime = current_fs_time(source_dir->i_sb);
++
+ cifs_rename_exit:
+       kfree(info_buf_source);
+       kfree(from_name);
diff --git a/queue-3.10/cifs-fix-wrong-filename-length-for-smb2.patch b/queue-3.10/cifs-fix-wrong-filename-length-for-smb2.patch
new file mode 100644 (file)
index 0000000..a586267
--- /dev/null
@@ -0,0 +1,84 @@
+From 1bbe4997b13de903c421c1cc78440e544b5f9064 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Fri, 22 Aug 2014 13:32:11 +0400
+Subject: CIFS: Fix wrong filename length for SMB2
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 1bbe4997b13de903c421c1cc78440e544b5f9064 upstream.
+
+The existing code uses the old MAX_NAME constant. This causes
+XFS test generic/013 to fail. Fix it by replacing MAX_NAME with
+PATH_MAX that SMB1 uses. Also remove an unused MAX_NAME constant
+definition.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsglob.h  |    5 -----
+ fs/cifs/smb2file.c  |    2 +-
+ fs/cifs/smb2inode.c |    2 +-
+ fs/cifs/smb2ops.c   |    2 +-
+ fs/cifs/smb2pdu.c   |    2 +-
+ 5 files changed, 4 insertions(+), 9 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -74,11 +74,6 @@
+ #define SERVER_NAME_LENGTH 40
+ #define SERVER_NAME_LEN_WITH_NULL     (SERVER_NAME_LENGTH + 1)
+-/* used to define string lengths for reversing unicode strings */
+-/*         (256+1)*2 = 514                                     */
+-/*           (max path length + 1 for null) * 2 for unicode    */
+-#define MAX_NAME 514
+-
+ /* SMB echo "timeout" -- FIXME: tunable? */
+ #define SMB_ECHO_INTERVAL (60 * HZ)
+--- a/fs/cifs/smb2file.c
++++ b/fs/cifs/smb2file.c
+@@ -73,7 +73,7 @@ smb2_open_file(const unsigned int xid, s
+               goto out;
+       }
+-      smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++      smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+                           GFP_KERNEL);
+       if (smb2_data == NULL) {
+               rc = -ENOMEM;
+--- a/fs/cifs/smb2inode.c
++++ b/fs/cifs/smb2inode.c
+@@ -123,7 +123,7 @@ smb2_query_path_info(const unsigned int
+       *adjust_tz = false;
+-      smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++      smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+                           GFP_KERNEL);
+       if (smb2_data == NULL)
+               return -ENOMEM;
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -243,7 +243,7 @@ smb2_query_file_info(const unsigned int
+       int rc;
+       struct smb2_file_all_info *smb2_data;
+-      smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++      smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+                           GFP_KERNEL);
+       if (smb2_data == NULL)
+               return -ENOMEM;
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1204,7 +1204,7 @@ SMB2_query_info(const unsigned int xid,
+ {
+       return query_info(xid, tcon, persistent_fid, volatile_fid,
+                         FILE_ALL_INFORMATION,
+-                        sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++                        sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+                         sizeof(struct smb2_file_all_info), data);
+ }
diff --git a/queue-3.10/cifs-fix-wrong-restart-readdir-for-smb1.patch b/queue-3.10/cifs-fix-wrong-restart-readdir-for-smb1.patch
new file mode 100644 (file)
index 0000000..0c8c9b9
--- /dev/null
@@ -0,0 +1,35 @@
+From f736906a7669a77cf8cabdcbcf1dc8cb694e12ef Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Tue, 26 Aug 2014 19:04:44 +0400
+Subject: CIFS: Fix wrong restart readdir for SMB1
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit f736906a7669a77cf8cabdcbcf1dc8cb694e12ef upstream.
+
+The existing code calls server->ops->close() that is not
+right. This causes XFS test generic/310 to fail. Fix this
+by using server->ops->closedir() function.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/readdir.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -585,8 +585,8 @@ find_cifs_entry(const unsigned int xid,
+               if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
+                       cfile->invalidHandle = true;
+                       spin_unlock(&cifs_file_list_lock);
+-                      if (server->ops->close)
+-                              server->ops->close(xid, tcon, &cfile->fid);
++                      if (server->ops->close_dir)
++                              server->ops->close_dir(xid, tcon, &cfile->fid);
+               } else
+                       spin_unlock(&cifs_file_list_lock);
+               if (cfile->srch_inf.ntwrk_buf_start) {
diff --git a/queue-3.10/cifs-possible-null-ptr-deref-in-smb2_tcon.patch b/queue-3.10/cifs-possible-null-ptr-deref-in-smb2_tcon.patch
new file mode 100644 (file)
index 0000000..47699f5
--- /dev/null
@@ -0,0 +1,32 @@
+From 18f39e7be0121317550d03e267e3ebd4dbfbb3ce Mon Sep 17 00:00:00 2001
+From: Steve French <smfrench@gmail.com>
+Date: Sun, 17 Aug 2014 00:22:24 -0500
+Subject: CIFS: Possible null ptr deref in SMB2_tcon
+
+From: Steve French <smfrench@gmail.com>
+
+commit 18f39e7be0121317550d03e267e3ebd4dbfbb3ce upstream.
+
+As Raphael Geissert pointed out, tcon_error_exit can dereference tcon
+and there is one path in which tcon can be null.
+
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reported-by: Raphael Geissert <geissert@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2pdu.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -809,7 +809,8 @@ tcon_exit:
+ tcon_error_exit:
+       if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
+               cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
+-              tcon->bad_network_name = true;
++              if (tcon)
++                      tcon->bad_network_name = true;
+       }
+       goto tcon_exit;
+ }
diff --git a/queue-3.10/ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch b/queue-3.10/ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch
new file mode 100644 (file)
index 0000000..4109cd8
--- /dev/null
@@ -0,0 +1,154 @@
+From bcc05910359183b431da92713e98eed478edf83a Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bvanassche@acm.org>
+Date: Wed, 9 Jul 2014 15:57:26 +0200
+Subject: IB/srp: Fix deadlock between host removal and multipathd
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+commit bcc05910359183b431da92713e98eed478edf83a upstream.
+
+If scsi_remove_host() is invoked after a SCSI device has been blocked,
+if the fast_io_fail_tmo or dev_loss_tmo work gets scheduled on the
+workqueue executing srp_remove_work() and if an I/O request is
+scheduled after the SCSI device had been blocked by e.g. multipathd
+then the following deadlock can occur:
+
+    kworker/6:1     D ffff880831f3c460     0   195      2 0x00000000
+    Call Trace:
+     [<ffffffff814aafd9>] schedule+0x29/0x70
+     [<ffffffff814aa0ef>] schedule_timeout+0x10f/0x2a0
+     [<ffffffff8105af6f>] msleep+0x2f/0x40
+     [<ffffffff8123b0ae>] __blk_drain_queue+0x4e/0x180
+     [<ffffffff8123d2d5>] blk_cleanup_queue+0x225/0x230
+     [<ffffffffa0010732>] __scsi_remove_device+0x62/0xe0 [scsi_mod]
+     [<ffffffffa000ed2f>] scsi_forget_host+0x6f/0x80 [scsi_mod]
+     [<ffffffffa0002eba>] scsi_remove_host+0x7a/0x130 [scsi_mod]
+     [<ffffffffa07cf5c5>] srp_remove_work+0x95/0x180 [ib_srp]
+     [<ffffffff8106d7aa>] process_one_work+0x1ea/0x6c0
+     [<ffffffff8106dd9b>] worker_thread+0x11b/0x3a0
+     [<ffffffff810758bd>] kthread+0xed/0x110
+     [<ffffffff814b972c>] ret_from_fork+0x7c/0xb0
+    multipathd      D ffff880096acc460     0  5340      1 0x00000000
+    Call Trace:
+     [<ffffffff814aafd9>] schedule+0x29/0x70
+     [<ffffffff814aa0ef>] schedule_timeout+0x10f/0x2a0
+     [<ffffffff814ab79b>] io_schedule_timeout+0x9b/0xf0
+     [<ffffffff814abe1c>] wait_for_completion_io_timeout+0xdc/0x110
+     [<ffffffff81244b9b>] blk_execute_rq+0x9b/0x100
+     [<ffffffff8124f665>] sg_io+0x1a5/0x450
+     [<ffffffff8124fd21>] scsi_cmd_ioctl+0x2a1/0x430
+     [<ffffffff8124fef2>] scsi_cmd_blk_ioctl+0x42/0x50
+     [<ffffffffa00ec97e>] sd_ioctl+0xbe/0x140 [sd_mod]
+     [<ffffffff8124bd04>] blkdev_ioctl+0x234/0x840
+     [<ffffffff811cb491>] block_ioctl+0x41/0x50
+     [<ffffffff811a0df0>] do_vfs_ioctl+0x300/0x520
+     [<ffffffff811a1051>] SyS_ioctl+0x41/0x80
+     [<ffffffff814b9962>] tracesys+0xd0/0xd5
+
+Fix this by scheduling removal work on another workqueue than the
+transport layer timers.
+
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
+Reviewed-by: David Dillow <dave@thedillows.org>
+Cc: Sebastian Parschauer <sebastian.riemer@profitbricks.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c |   38 ++++++++++++++++++++++++++----------
+ 1 file changed, 28 insertions(+), 10 deletions(-)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -93,6 +93,7 @@ static void srp_send_completion(struct i
+ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
+ static struct scsi_transport_template *ib_srp_transport_template;
++static struct workqueue_struct *srp_remove_wq;
+ static struct ib_client srp_client = {
+       .name   = "srp",
+@@ -456,7 +457,7 @@ static bool srp_queue_remove_work(struct
+       spin_unlock_irq(&target->lock);
+       if (changed)
+-              queue_work(system_long_wq, &target->remove_work);
++              queue_work(srp_remove_wq, &target->remove_work);
+       return changed;
+ }
+@@ -2530,9 +2531,10 @@ static void srp_remove_one(struct ib_dev
+               spin_unlock(&host->target_lock);
+               /*
+-               * Wait for target port removal tasks.
++               * Wait for tl_err and target port removal tasks.
+                */
+               flush_workqueue(system_long_wq);
++              flush_workqueue(srp_remove_wq);
+               kfree(host);
+       }
+@@ -2577,16 +2579,22 @@ static int __init srp_init_module(void)
+               indirect_sg_entries = cmd_sg_entries;
+       }
++      srp_remove_wq = create_workqueue("srp_remove");
++      if (IS_ERR(srp_remove_wq)) {
++              ret = PTR_ERR(srp_remove_wq);
++              goto out;
++      }
++
++      ret = -ENOMEM;
+       ib_srp_transport_template =
+               srp_attach_transport(&ib_srp_transport_functions);
+       if (!ib_srp_transport_template)
+-              return -ENOMEM;
++              goto destroy_wq;
+       ret = class_register(&srp_class);
+       if (ret) {
+               pr_err("couldn't register class infiniband_srp\n");
+-              srp_release_transport(ib_srp_transport_template);
+-              return ret;
++              goto release_tr;
+       }
+       ib_sa_register_client(&srp_sa_client);
+@@ -2594,13 +2602,22 @@ static int __init srp_init_module(void)
+       ret = ib_register_client(&srp_client);
+       if (ret) {
+               pr_err("couldn't register IB client\n");
+-              srp_release_transport(ib_srp_transport_template);
+-              ib_sa_unregister_client(&srp_sa_client);
+-              class_unregister(&srp_class);
+-              return ret;
++              goto unreg_sa;
+       }
+-      return 0;
++out:
++      return ret;
++
++unreg_sa:
++      ib_sa_unregister_client(&srp_sa_client);
++      class_unregister(&srp_class);
++
++release_tr:
++      srp_release_transport(ib_srp_transport_template);
++
++destroy_wq:
++      destroy_workqueue(srp_remove_wq);
++      goto out;
+ }
+ static void __exit srp_cleanup_module(void)
+@@ -2609,6 +2626,7 @@ static void __exit srp_cleanup_module(vo
+       ib_sa_unregister_client(&srp_sa_client);
+       class_unregister(&srp_class);
+       srp_release_transport(ib_srp_transport_template);
++      destroy_workqueue(srp_remove_wq);
+ }
+ module_init(srp_init_module);
diff --git a/queue-3.10/libceph-add-process_one_ticket-helper.patch b/queue-3.10/libceph-add-process_one_ticket-helper.patch
new file mode 100644 (file)
index 0000000..5c20cb1
--- /dev/null
@@ -0,0 +1,278 @@
+From 597cda357716a3cf8d994cb11927af917c8d71fa Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+Date: Mon, 8 Sep 2014 17:25:34 +0400
+Subject: libceph: add process_one_ticket() helper
+
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+
+commit 597cda357716a3cf8d994cb11927af917c8d71fa upstream.
+
+Add a helper for processing individual cephx auth tickets.  Needed for
+the next commit, which deals with allocating ticket buffers.  (Most of
+the diff here is whitespace - view with git diff -b).
+
+Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |  228 +++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 124 insertions(+), 104 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -129,17 +129,131 @@ static void remove_ticket_handler(struct
+       kfree(th);
+ }
++static int process_one_ticket(struct ceph_auth_client *ac,
++                            struct ceph_crypto_key *secret,
++                            void **p, void *end,
++                            void *dbuf, void *ticket_buf)
++{
++      struct ceph_x_info *xi = ac->private;
++      int type;
++      u8 tkt_struct_v, blob_struct_v;
++      struct ceph_x_ticket_handler *th;
++      void *dp, *dend;
++      int dlen;
++      char is_enc;
++      struct timespec validity;
++      struct ceph_crypto_key old_key;
++      void *tp, *tpend;
++      struct ceph_timespec new_validity;
++      struct ceph_crypto_key new_session_key;
++      struct ceph_buffer *new_ticket_blob;
++      unsigned long new_expires, new_renew_after;
++      u64 new_secret_id;
++      int ret;
++
++      ceph_decode_need(p, end, sizeof(u32) + 1, bad);
++
++      type = ceph_decode_32(p);
++      dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
++
++      tkt_struct_v = ceph_decode_8(p);
++      if (tkt_struct_v != 1)
++              goto bad;
++
++      th = get_ticket_handler(ac, type);
++      if (IS_ERR(th)) {
++              ret = PTR_ERR(th);
++              goto out;
++      }
++
++      /* blob for me */
++      dlen = ceph_x_decrypt(secret, p, end, dbuf,
++                            TEMP_TICKET_BUF_LEN);
++      if (dlen <= 0) {
++              ret = dlen;
++              goto out;
++      }
++      dout(" decrypted %d bytes\n", dlen);
++      dp = dbuf;
++      dend = dp + dlen;
++
++      tkt_struct_v = ceph_decode_8(&dp);
++      if (tkt_struct_v != 1)
++              goto bad;
++
++      memcpy(&old_key, &th->session_key, sizeof(old_key));
++      ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
++      if (ret)
++              goto out;
++
++      ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
++      ceph_decode_timespec(&validity, &new_validity);
++      new_expires = get_seconds() + validity.tv_sec;
++      new_renew_after = new_expires - (validity.tv_sec / 4);
++      dout(" expires=%lu renew_after=%lu\n", new_expires,
++           new_renew_after);
++
++      /* ticket blob for service */
++      ceph_decode_8_safe(p, end, is_enc, bad);
++      tp = ticket_buf;
++      if (is_enc) {
++              /* encrypted */
++              dout(" encrypted ticket\n");
++              dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
++                                    TEMP_TICKET_BUF_LEN);
++              if (dlen < 0) {
++                      ret = dlen;
++                      goto out;
++              }
++              dlen = ceph_decode_32(&tp);
++      } else {
++              /* unencrypted */
++              ceph_decode_32_safe(p, end, dlen, bad);
++              ceph_decode_need(p, end, dlen, bad);
++              ceph_decode_copy(p, ticket_buf, dlen);
++      }
++      tpend = tp + dlen;
++      dout(" ticket blob is %d bytes\n", dlen);
++      ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
++      blob_struct_v = ceph_decode_8(&tp);
++      new_secret_id = ceph_decode_64(&tp);
++      ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
++      if (ret)
++              goto out;
++
++      /* all is well, update our ticket */
++      ceph_crypto_key_destroy(&th->session_key);
++      if (th->ticket_blob)
++              ceph_buffer_put(th->ticket_blob);
++      th->session_key = new_session_key;
++      th->ticket_blob = new_ticket_blob;
++      th->validity = new_validity;
++      th->secret_id = new_secret_id;
++      th->expires = new_expires;
++      th->renew_after = new_renew_after;
++      dout(" got ticket service %d (%s) secret_id %lld len %d\n",
++           type, ceph_entity_type_name(type), th->secret_id,
++           (int)th->ticket_blob->vec.iov_len);
++      xi->have_keys |= th->service;
++
++out:
++      return ret;
++
++bad:
++      ret = -EINVAL;
++      goto out;
++}
++
+ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
+                                   struct ceph_crypto_key *secret,
+                                   void *buf, void *end)
+ {
+-      struct ceph_x_info *xi = ac->private;
+-      int num;
+       void *p = buf;
+-      int ret;
+       char *dbuf;
+       char *ticket_buf;
+       u8 reply_struct_v;
++      u32 num;
++      int ret;
+       dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+       if (!dbuf)
+@@ -150,112 +264,18 @@ static int ceph_x_proc_ticket_reply(stru
+       if (!ticket_buf)
+               goto out_dbuf;
+-      ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
+-      reply_struct_v = ceph_decode_8(&p);
++      ceph_decode_8_safe(&p, end, reply_struct_v, bad);
+       if (reply_struct_v != 1)
+-              goto bad;
+-      num = ceph_decode_32(&p);
+-      dout("%d tickets\n", num);
+-      while (num--) {
+-              int type;
+-              u8 tkt_struct_v, blob_struct_v;
+-              struct ceph_x_ticket_handler *th;
+-              void *dp, *dend;
+-              int dlen;
+-              char is_enc;
+-              struct timespec validity;
+-              struct ceph_crypto_key old_key;
+-              void *tp, *tpend;
+-              struct ceph_timespec new_validity;
+-              struct ceph_crypto_key new_session_key;
+-              struct ceph_buffer *new_ticket_blob;
+-              unsigned long new_expires, new_renew_after;
+-              u64 new_secret_id;
+-
+-              ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
+-
+-              type = ceph_decode_32(&p);
+-              dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
+-
+-              tkt_struct_v = ceph_decode_8(&p);
+-              if (tkt_struct_v != 1)
+-                      goto bad;
+-
+-              th = get_ticket_handler(ac, type);
+-              if (IS_ERR(th)) {
+-                      ret = PTR_ERR(th);
+-                      goto out;
+-              }
+-
+-              /* blob for me */
+-              dlen = ceph_x_decrypt(secret, &p, end, dbuf,
+-                                    TEMP_TICKET_BUF_LEN);
+-              if (dlen <= 0) {
+-                      ret = dlen;
+-                      goto out;
+-              }
+-              dout(" decrypted %d bytes\n", dlen);
+-              dend = dbuf + dlen;
+-              dp = dbuf;
+-
+-              tkt_struct_v = ceph_decode_8(&dp);
+-              if (tkt_struct_v != 1)
+-                      goto bad;
++              return -EINVAL;
+-              memcpy(&old_key, &th->session_key, sizeof(old_key));
+-              ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
+-              if (ret)
+-                      goto out;
++      ceph_decode_32_safe(&p, end, num, bad);
++      dout("%d tickets\n", num);
+-              ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
+-              ceph_decode_timespec(&validity, &new_validity);
+-              new_expires = get_seconds() + validity.tv_sec;
+-              new_renew_after = new_expires - (validity.tv_sec / 4);
+-              dout(" expires=%lu renew_after=%lu\n", new_expires,
+-                   new_renew_after);
+-
+-              /* ticket blob for service */
+-              ceph_decode_8_safe(&p, end, is_enc, bad);
+-              tp = ticket_buf;
+-              if (is_enc) {
+-                      /* encrypted */
+-                      dout(" encrypted ticket\n");
+-                      dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf,
+-                                            TEMP_TICKET_BUF_LEN);
+-                      if (dlen < 0) {
+-                              ret = dlen;
+-                              goto out;
+-                      }
+-                      dlen = ceph_decode_32(&tp);
+-              } else {
+-                      /* unencrypted */
+-                      ceph_decode_32_safe(&p, end, dlen, bad);
+-                      ceph_decode_need(&p, end, dlen, bad);
+-                      ceph_decode_copy(&p, ticket_buf, dlen);
+-              }
+-              tpend = tp + dlen;
+-              dout(" ticket blob is %d bytes\n", dlen);
+-              ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
+-              blob_struct_v = ceph_decode_8(&tp);
+-              new_secret_id = ceph_decode_64(&tp);
+-              ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
++      while (num--) {
++              ret = process_one_ticket(ac, secret, &p, end,
++                                       dbuf, ticket_buf);
+               if (ret)
+                       goto out;
+-
+-              /* all is well, update our ticket */
+-              ceph_crypto_key_destroy(&th->session_key);
+-              if (th->ticket_blob)
+-                      ceph_buffer_put(th->ticket_blob);
+-              th->session_key = new_session_key;
+-              th->ticket_blob = new_ticket_blob;
+-              th->validity = new_validity;
+-              th->secret_id = new_secret_id;
+-              th->expires = new_expires;
+-              th->renew_after = new_renew_after;
+-              dout(" got ticket service %d (%s) secret_id %lld len %d\n",
+-                   type, ceph_entity_type_name(type), th->secret_id,
+-                   (int)th->ticket_blob->vec.iov_len);
+-              xi->have_keys |= th->service;
+       }
+       ret = 0;
diff --git a/queue-3.10/libceph-do-not-hard-code-max-auth-ticket-len.patch b/queue-3.10/libceph-do-not-hard-code-max-auth-ticket-len.patch
new file mode 100644 (file)
index 0000000..75fa81b
--- /dev/null
@@ -0,0 +1,198 @@
+From c27a3e4d667fdcad3db7b104f75659478e0c68d8 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+Date: Tue, 9 Sep 2014 19:39:15 +0400
+Subject: libceph: do not hard code max auth ticket len
+
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+
+commit c27a3e4d667fdcad3db7b104f75659478e0c68d8 upstream.
+
+We hard code cephx auth ticket buffer size to 256 bytes.  This isn't
+enough for any moderate setups and, in case tickets themselves are not
+encrypted, leads to buffer overflows (ceph_x_decrypt() errors out, but
+ceph_decode_copy() doesn't - it's just a memcpy() wrapper).  Since the
+buffer is allocated dynamically anyway, allocated it a bit later, at
+the point where we know how much is going to be needed.
+
+Fixes: http://tracker.ceph.com/issues/8979
+
+Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c |   64 ++++++++++++++++++++++++------------------------------
+ 1 file changed, 29 insertions(+), 35 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -13,8 +13,6 @@
+ #include "auth_x.h"
+ #include "auth_x_protocol.h"
+-#define TEMP_TICKET_BUF_LEN   256
+-
+ static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
+ static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
+@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_cr
+ }
+ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
+-                        void **p, void *end, void *obuf, size_t olen)
++                        void **p, void *end, void **obuf, size_t olen)
+ {
+       struct ceph_x_encrypt_header head;
+       size_t head_len = sizeof(head);
+@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_cr
+               return -EINVAL;
+       dout("ceph_x_decrypt len %d\n", len);
+-      ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
+-                          *p, len);
++      if (*obuf == NULL) {
++              *obuf = kmalloc(len, GFP_NOFS);
++              if (!*obuf)
++                      return -ENOMEM;
++              olen = len;
++      }
++
++      ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
+       if (ret)
+               return ret;
+       if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
+@@ -131,18 +135,19 @@ static void remove_ticket_handler(struct
+ static int process_one_ticket(struct ceph_auth_client *ac,
+                             struct ceph_crypto_key *secret,
+-                            void **p, void *end,
+-                            void *dbuf, void *ticket_buf)
++                            void **p, void *end)
+ {
+       struct ceph_x_info *xi = ac->private;
+       int type;
+       u8 tkt_struct_v, blob_struct_v;
+       struct ceph_x_ticket_handler *th;
++      void *dbuf = NULL;
+       void *dp, *dend;
+       int dlen;
+       char is_enc;
+       struct timespec validity;
+       struct ceph_crypto_key old_key;
++      void *ticket_buf = NULL;
+       void *tp, *tpend;
+       struct ceph_timespec new_validity;
+       struct ceph_crypto_key new_session_key;
+@@ -167,8 +172,7 @@ static int process_one_ticket(struct cep
+       }
+       /* blob for me */
+-      dlen = ceph_x_decrypt(secret, p, end, dbuf,
+-                            TEMP_TICKET_BUF_LEN);
++      dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
+       if (dlen <= 0) {
+               ret = dlen;
+               goto out;
+@@ -195,20 +199,25 @@ static int process_one_ticket(struct cep
+       /* ticket blob for service */
+       ceph_decode_8_safe(p, end, is_enc, bad);
+-      tp = ticket_buf;
+       if (is_enc) {
+               /* encrypted */
+               dout(" encrypted ticket\n");
+-              dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
+-                                    TEMP_TICKET_BUF_LEN);
++              dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
+               if (dlen < 0) {
+                       ret = dlen;
+                       goto out;
+               }
++              tp = ticket_buf;
+               dlen = ceph_decode_32(&tp);
+       } else {
+               /* unencrypted */
+               ceph_decode_32_safe(p, end, dlen, bad);
++              ticket_buf = kmalloc(dlen, GFP_NOFS);
++              if (!ticket_buf) {
++                      ret = -ENOMEM;
++                      goto out;
++              }
++              tp = ticket_buf;
+               ceph_decode_need(p, end, dlen, bad);
+               ceph_decode_copy(p, ticket_buf, dlen);
+       }
+@@ -237,6 +246,8 @@ static int process_one_ticket(struct cep
+       xi->have_keys |= th->service;
+ out:
++      kfree(ticket_buf);
++      kfree(dbuf);
+       return ret;
+ bad:
+@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(stru
+                                   void *buf, void *end)
+ {
+       void *p = buf;
+-      char *dbuf;
+-      char *ticket_buf;
+       u8 reply_struct_v;
+       u32 num;
+       int ret;
+-      dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+-      if (!dbuf)
+-              return -ENOMEM;
+-
+-      ret = -ENOMEM;
+-      ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+-      if (!ticket_buf)
+-              goto out_dbuf;
+-
+       ceph_decode_8_safe(&p, end, reply_struct_v, bad);
+       if (reply_struct_v != 1)
+               return -EINVAL;
+@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(stru
+       dout("%d tickets\n", num);
+       while (num--) {
+-              ret = process_one_ticket(ac, secret, &p, end,
+-                                       dbuf, ticket_buf);
++              ret = process_one_ticket(ac, secret, &p, end);
+               if (ret)
+-                      goto out;
++                      return ret;
+       }
+-      ret = 0;
+-out:
+-      kfree(ticket_buf);
+-out_dbuf:
+-      kfree(dbuf);
+-      return ret;
++      return 0;
+ bad:
+-      ret = -EINVAL;
+-      goto out;
++      return -EINVAL;
+ }
+ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
+@@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_repl
+       struct ceph_x_ticket_handler *th;
+       int ret = 0;
+       struct ceph_x_authorize_reply reply;
++      void *preply = &reply;
+       void *p = au->reply_buf;
+       void *end = p + sizeof(au->reply_buf);
+       th = get_ticket_handler(ac, au->service);
+       if (IS_ERR(th))
+               return PTR_ERR(th);
+-      ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
++      ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
+       if (ret < 0)
+               return ret;
+       if (ret != sizeof(reply))
diff --git a/queue-3.10/libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch b/queue-3.10/libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch
new file mode 100644 (file)
index 0000000..c23e543
--- /dev/null
@@ -0,0 +1,55 @@
+From 5f740d7e1531099b888410e6bab13f68da9b1a4d Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+Date: Fri, 8 Aug 2014 12:43:39 +0400
+Subject: libceph: set last_piece in ceph_msg_data_pages_cursor_init()
+ correctly
+
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+
+commit 5f740d7e1531099b888410e6bab13f68da9b1a4d upstream.
+
+Determining ->last_piece based on the value of ->page_offset + length
+is incorrect because length here is the length of the entire message.
+->last_piece set to false even if page array data item length is <=
+PAGE_SIZE, which results in invalid length passed to
+ceph_tcp_{send,recv}page() and causes various asserts to fire.
+
+    # cat pages-cursor-init.sh
+    #!/bin/bash
+    rbd create --size 10 --image-format 2 foo
+    FOO_DEV=$(rbd map foo)
+    dd if=/dev/urandom of=$FOO_DEV bs=1M &>/dev/null
+    rbd snap create foo@snap
+    rbd snap protect foo@snap
+    rbd clone foo@snap bar
+    # rbd_resize calls librbd rbd_resize(), size is in bytes
+    ./rbd_resize bar $(((4 << 20) + 512))
+    rbd resize --size 10 bar
+    BAR_DEV=$(rbd map bar)
+    # trigger a 512-byte copyup -- 512-byte page array data item
+    dd if=/dev/urandom of=$BAR_DEV bs=1M count=1 seek=5
+
+The problem exists only in ceph_msg_data_pages_cursor_init(),
+ceph_msg_data_pages_advance() does the right thing.  The size_t cast is
+unnecessary.
+
+Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Reviewed-by: Alex Elder <elder@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/messenger.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -904,7 +904,7 @@ static void ceph_msg_data_pages_cursor_i
+       BUG_ON(page_count > (int)USHRT_MAX);
+       cursor->page_count = (unsigned short)page_count;
+       BUG_ON(length > SIZE_MAX - cursor->page_offset);
+-      cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE;
++      cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE;
+ }
+ static struct page *
diff --git a/queue-3.10/mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch b/queue-3.10/mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch
new file mode 100644 (file)
index 0000000..a7bd18d
--- /dev/null
@@ -0,0 +1,98 @@
+From a152056c912db82860a8b4c23d0bd3a5aa89e363 Mon Sep 17 00:00:00 2001
+From: Kevin Hao <haokexin@gmail.com>
+Date: Thu, 3 Jul 2014 10:35:26 +0800
+Subject: mtd/ftl: fix the double free of the buffers allocated in build_maps()
+
+From: Kevin Hao <haokexin@gmail.com>
+
+commit a152056c912db82860a8b4c23d0bd3a5aa89e363 upstream.
+
+I got the following panic on my fsl p5020ds board.
+
+  Unable to handle kernel paging request for data at address 0x7375627379737465
+  Faulting instruction address: 0xc000000000100778
+  Oops: Kernel access of bad area, sig: 11 [#1]
+  SMP NR_CPUS=24 CoreNet Generic
+  Modules linked in:
+  CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.15.0-next-20140613 #145
+  task: c0000000fe080000 ti: c0000000fe088000 task.ti: c0000000fe088000
+  NIP: c000000000100778 LR: c00000000010073c CTR: 0000000000000000
+  REGS: c0000000fe08aa00 TRAP: 0300   Not tainted  (3.15.0-next-20140613)
+  MSR: 0000000080029000 <CE,EE,ME>  CR: 24ad2e24  XER: 00000000
+  DEAR: 7375627379737465 ESR: 0000000000000000 SOFTE: 1
+  GPR00: c0000000000c99b0 c0000000fe08ac80 c0000000009598e0 c0000000fe001d80
+  GPR04: 00000000000000d0 0000000000000913 c000000007902b20 0000000000000000
+  GPR08: c0000000feaae888 0000000000000000 0000000007091000 0000000000200200
+  GPR12: 0000000028ad2e28 c00000000fff4000 c0000000007abe08 0000000000000000
+  GPR16: c0000000007ab160 c0000000007aaf98 c00000000060ba68 c0000000007abda8
+  GPR20: c0000000007abde8 c0000000feaea6f8 c0000000feaea708 c0000000007abd10
+  GPR24: c000000000989370 c0000000008c6228 00000000000041ed c0000000fe00a400
+  GPR28: c00000000017c1cc 00000000000000d0 7375627379737465 c0000000fe001d80
+  NIP [c000000000100778] .__kmalloc_track_caller+0x70/0x168
+  LR [c00000000010073c] .__kmalloc_track_caller+0x34/0x168
+  Call Trace:
+  [c0000000fe08ac80] [c00000000087e6b8] uevent_sock_list+0x0/0x10 (unreliable)
+  [c0000000fe08ad20] [c0000000000c99b0] .kstrdup+0x44/0x90
+  [c0000000fe08adc0] [c00000000017c1cc] .__kernfs_new_node+0x4c/0x130
+  [c0000000fe08ae70] [c00000000017d7e4] .kernfs_new_node+0x2c/0x64
+  [c0000000fe08aef0] [c00000000017db00] .kernfs_create_dir_ns+0x34/0xc8
+  [c0000000fe08af80] [c00000000018067c] .sysfs_create_dir_ns+0x58/0xcc
+  [c0000000fe08b010] [c0000000002c711c] .kobject_add_internal+0xc8/0x384
+  [c0000000fe08b0b0] [c0000000002c7644] .kobject_add+0x64/0xc8
+  [c0000000fe08b140] [c000000000355ebc] .device_add+0x11c/0x654
+  [c0000000fe08b200] [c0000000002b5988] .add_disk+0x20c/0x4b4
+  [c0000000fe08b2c0] [c0000000003a21d4] .add_mtd_blktrans_dev+0x340/0x514
+  [c0000000fe08b350] [c0000000003a3410] .mtdblock_add_mtd+0x74/0xb4
+  [c0000000fe08b3e0] [c0000000003a32cc] .blktrans_notify_add+0x64/0x94
+  [c0000000fe08b470] [c00000000039b5b4] .add_mtd_device+0x1d4/0x368
+  [c0000000fe08b520] [c00000000039b830] .mtd_device_parse_register+0xe8/0x104
+  [c0000000fe08b5c0] [c0000000003b8408] .of_flash_probe+0x72c/0x734
+  [c0000000fe08b750] [c00000000035ba40] .platform_drv_probe+0x38/0x84
+  [c0000000fe08b7d0] [c0000000003599a4] .really_probe+0xa4/0x29c
+  [c0000000fe08b870] [c000000000359d3c] .__driver_attach+0x100/0x104
+  [c0000000fe08b900] [c00000000035746c] .bus_for_each_dev+0x84/0xe4
+  [c0000000fe08b9a0] [c0000000003593c0] .driver_attach+0x24/0x38
+  [c0000000fe08ba10] [c000000000358f24] .bus_add_driver+0x1c8/0x2ac
+  [c0000000fe08bab0] [c00000000035a3a4] .driver_register+0x8c/0x158
+  [c0000000fe08bb30] [c00000000035b9f4] .__platform_driver_register+0x6c/0x80
+  [c0000000fe08bba0] [c00000000084e080] .of_flash_driver_init+0x1c/0x30
+  [c0000000fe08bc10] [c000000000001864] .do_one_initcall+0xbc/0x238
+  [c0000000fe08bd00] [c00000000082cdc0] .kernel_init_freeable+0x188/0x268
+  [c0000000fe08bdb0] [c0000000000020a0] .kernel_init+0x1c/0xf7c
+  [c0000000fe08be30] [c000000000000884] .ret_from_kernel_thread+0x58/0xd4
+  Instruction dump:
+  41bd0010 480000c8 4bf04eb5 60000000 e94d0028 e93f0000 7cc95214 e8a60008
+  7fc9502a 2fbe0000 419e00c8 e93f0022 <7f7e482a> 39200000 88ed06b2 992d06b2
+  ---[ end trace b4c9a94804a42d40 ]---
+
+It seems that the corrupted partition header on my mtd device triggers
+a bug in the ftl. In function build_maps() it will allocate the buffers
+needed by the mtd partition, but if something goes wrong such as kmalloc
+failure, mtd read error or invalid partition header parameter, it will
+free all allocated buffers and then return non-zero. In my case, it
+seems that partition header parameter 'NumTransferUnits' is invalid.
+
+And the ftl_freepart() is a function which free all the partition
+buffers allocated by build_maps(). Given the build_maps() is a self
+cleaning function, so there is no need to invoke this function even
+if build_maps() return with error. Otherwise it will causes the
+buffers to be freed twice and then weird things would happen.
+
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/ftl.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/mtd/ftl.c
++++ b/drivers/mtd/ftl.c
+@@ -1075,7 +1075,6 @@ static void ftl_add_mtd(struct mtd_blktr
+                       return;
+       }
+-      ftl_freepart(partition);
+       kfree(partition);
+ }
diff --git a/queue-3.10/mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch b/queue-3.10/mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch
new file mode 100644 (file)
index 0000000..f2e106a
--- /dev/null
@@ -0,0 +1,45 @@
+From 40ddbf5069bd4e11447c0088fc75318e0aac53f0 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 25 Aug 2014 16:15:33 -0700
+Subject: mtd: nand: omap: Fix 1-bit Hamming code scheme, omap_calculate_ecc()
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 40ddbf5069bd4e11447c0088fc75318e0aac53f0 upstream.
+
+commit 65b97cf6b8de introduced in v3.7 caused a regression
+by using a reversed CS_MASK thus causing omap_calculate_ecc to
+always fail. As the NAND base driver never checks for .calculate()'s
+return value, the zeroed ECC values are used as is without showing
+any error to the user. However, this won't work and the NAND device
+won't be guarded by any error code.
+
+Fix the issue by using the correct mask.
+
+Code was tested on omap3beagle using the following procedure
+- flash the primary bootloader (MLO) from the kernel to the first
+NAND partition using nandwrite.
+- boot the board from NAND. This utilizes OMAP ROM loader that
+relies on 1-bit Hamming code ECC.
+
+Fixes: 65b97cf6b8de (mtd: nand: omap2: handle nand on gpmc)
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/nand/omap2.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -948,7 +948,7 @@ static int omap_calculate_ecc(struct mtd
+       u32 val;
+       val = readl(info->reg.gpmc_ecc_config);
+-      if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
++      if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs)
+               return -EINVAL;
+       /* read ecc result */
index ae86dba1134b95d50b7741b269c0db681557e2a8..7fdecf3ca2fc1d3251d1f73f0163b51fa7b58fc0 100644 (file)
@@ -53,3 +53,16 @@ xfs-don-t-dirty-buffers-beyond-eof.patch
 xfs-don-t-zero-partial-page-cache-pages-during-o_direct-writes.patch
 xfs-don-t-zero-partial-page-cache-pages-during.patch
 md-raid1-raid10-always-abort-recover-on-write-error.patch
+libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch
+libceph-add-process_one_ticket-helper.patch
+libceph-do-not-hard-code-max-auth-ticket-len.patch
+cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch
+cifs-fix-async-reading-on-reconnects.patch
+cifs-possible-null-ptr-deref-in-smb2_tcon.patch
+cifs-fix-wrong-directory-attributes-after-rename.patch
+cifs-fix-wrong-filename-length-for-smb2.patch
+cifs-fix-wrong-restart-readdir-for-smb1.patch
+mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch
+mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch
+blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch
+ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch