]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Aug 2013 05:53:42 +0000 (22:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Aug 2013 05:53:42 +0000 (22:53 -0700)
added patches:
cifs-extend-the-buffer-length-enought-for-sprintf-using.patch
debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch
ext4-fix-mount-remount-error-messages-for-incompatible-mount-options.patch
usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch

queue-3.4/cifs-extend-the-buffer-length-enought-for-sprintf-using.patch [new file with mode: 0644]
queue-3.4/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch [new file with mode: 0644]
queue-3.4/ext4-fix-mount-remount-error-messages-for-incompatible-mount-options.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch [new file with mode: 0644]

diff --git a/queue-3.4/cifs-extend-the-buffer-length-enought-for-sprintf-using.patch b/queue-3.4/cifs-extend-the-buffer-length-enought-for-sprintf-using.patch
new file mode 100644 (file)
index 0000000..c5e7231
--- /dev/null
@@ -0,0 +1,99 @@
+From 057d6332b24a4497c55a761c83c823eed9e3f23b Mon Sep 17 00:00:00 2001
+From: Chen Gang <gang.chen@asianux.com>
+Date: Fri, 19 Jul 2013 09:01:36 +0800
+Subject: cifs: extend the buffer length enought for sprintf() using
+
+From: Chen Gang <gang.chen@asianux.com>
+
+commit 057d6332b24a4497c55a761c83c823eed9e3f23b upstream.
+
+For cifs_set_cifscreds() in "fs/cifs/connect.c", 'desc' buffer length
+is 'CIFSCREDS_DESC_SIZE' (56 is less than 256), and 'ses->domainName'
+length may be "255 + '\0'".
+
+The related sprintf() may cause memory overflow, so need extend related
+buffer enough to hold all things.
+
+It is also necessary to be sure of 'ses->domainName' must be less than
+256, and define the related macro instead of hard code number '256'.
+
+Signed-off-by: Chen Gang <gang.chen@asianux.com>
+Reviewed-by: Jeff Layton <jlayton@redhat.com>
+Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
+Reviewed-by: Scott Lovenberg <scott.lovenberg@gmail.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsencrypt.c |    2 +-
+ fs/cifs/cifsglob.h    |    1 +
+ fs/cifs/connect.c     |    7 ++++---
+ fs/cifs/sess.c        |    6 +++---
+ 4 files changed, 9 insertions(+), 7 deletions(-)
+
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -369,7 +369,7 @@ find_domain_name(struct cifs_ses *ses, c
+               if (blobptr + attrsize > blobend)
+                       break;
+               if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
+-                      if (!attrsize)
++                      if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
+                               break;
+                       if (!ses->domainName) {
+                               ses->domainName =
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -38,6 +38,7 @@
+ #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
+ #define MAX_SERVER_SIZE 15
+ #define MAX_SHARE_SIZE 80
++#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */
+ #define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */
+ #define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -1698,7 +1698,8 @@ cifs_parse_mount_options(const char *mou
+                       if (string == NULL)
+                               goto out_nomem;
+-                      if (strnlen(string, 256) == 256) {
++                      if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
++                                      == CIFS_MAX_DOMAINNAME_LEN) {
+                               printk(KERN_WARNING "CIFS: domain name too"
+                                                   " long\n");
+                               goto cifs_parse_mount_err;
+@@ -2356,8 +2357,8 @@ cifs_put_smb_ses(struct cifs_ses *ses)
+ #ifdef CONFIG_KEYS
+-/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
+-#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
++/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
++#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
+ /* Populate username and pw fields from keyring if possible */
+ static int
+--- a/fs/cifs/sess.c
++++ b/fs/cifs/sess.c
+@@ -198,7 +198,7 @@ static void unicode_domain_string(char *
+               bytes_ret = 0;
+       } else
+               bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
+-                                          256, nls_cp);
++                                          CIFS_MAX_DOMAINNAME_LEN, nls_cp);
+       bcc_ptr += 2 * bytes_ret;
+       bcc_ptr += 2;  /* account for null terminator */
+@@ -256,8 +256,8 @@ static void ascii_ssetup_strings(char **
+       /* copy domain */
+       if (ses->domainName != NULL) {
+-              strncpy(bcc_ptr, ses->domainName, 256);
+-              bcc_ptr += strnlen(ses->domainName, 256);
++              strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
++              bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+       } /* else we will send a null domain name
+            so the server will default to its own domain */
+       *bcc_ptr = 0;
diff --git a/queue-3.4/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch b/queue-3.4/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch
new file mode 100644 (file)
index 0000000..6043e08
--- /dev/null
@@ -0,0 +1,166 @@
+From 776164c1faac4966ab14418bb0922e1820da1d19 Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Fri, 26 Jul 2013 17:12:56 +0200
+Subject: debugfs: debugfs_remove_recursive() must not rely on list_empty(d_subdirs)
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+commit 776164c1faac4966ab14418bb0922e1820da1d19 upstream.
+
+debugfs_remove_recursive() is wrong,
+
+1. it wrongly assumes that !list_empty(d_subdirs) means that this
+   dir should be removed.
+
+   This is not that bad by itself, but:
+
+2. if d_subdirs does not becomes empty after __debugfs_remove()
+   it gives up and silently fails, it doesn't even try to remove
+   other entries.
+
+   However ->d_subdirs can be non-empty because it still has the
+   already deleted !debugfs_positive() entries.
+
+3. simple_release_fs() is called even if __debugfs_remove() fails.
+
+Suppose we have
+
+       dir1/
+               dir2/
+                       file2
+               file1
+
+and someone opens dir1/dir2/file2.
+
+Now, debugfs_remove_recursive(dir1/dir2) succeeds, and dir1/dir2 goes
+away.
+
+But debugfs_remove_recursive(dir1) silently fails and doesn't remove
+this directory. Because it tries to delete (the already deleted)
+dir1/dir2/file2 again and then fails due to "Avoid infinite loop"
+logic.
+
+Test-case:
+
+       #!/bin/sh
+
+       cd /sys/kernel/debug/tracing
+       echo 'p:probe/sigprocmask sigprocmask' >> kprobe_events
+       sleep 1000 < events/probe/sigprocmask/id &
+       echo -n >| kprobe_events
+
+       [ -d events/probe ] && echo "ERR!! failed to rm probe"
+
+And after that it is not possible to create another probe entry.
+
+With this patch debugfs_remove_recursive() skips !debugfs_positive()
+files although this is not strictly needed. The most important change
+is that it does not try to make ->d_subdirs empty, it simply scans
+the whole list(s) recursively and removes as much as possible.
+
+Link: http://lkml.kernel.org/r/20130726151256.GC19472@redhat.com
+
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/debugfs/inode.c |   69 ++++++++++++++++-------------------------------------
+ 1 file changed, 22 insertions(+), 47 deletions(-)
+
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -527,8 +527,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
+  */
+ void debugfs_remove_recursive(struct dentry *dentry)
+ {
+-      struct dentry *child;
+-      struct dentry *parent;
++      struct dentry *child, *next, *parent;
+       if (!dentry)
+               return;
+@@ -538,61 +537,37 @@ void debugfs_remove_recursive(struct den
+               return;
+       parent = dentry;
++ down:
+       mutex_lock(&parent->d_inode->i_mutex);
++      list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
++              if (!debugfs_positive(child))
++                      continue;
+-      while (1) {
+-              /*
+-               * When all dentries under "parent" has been removed,
+-               * walk up the tree until we reach our starting point.
+-               */
+-              if (list_empty(&parent->d_subdirs)) {
+-                      mutex_unlock(&parent->d_inode->i_mutex);
+-                      if (parent == dentry)
+-                              break;
+-                      parent = parent->d_parent;
+-                      mutex_lock(&parent->d_inode->i_mutex);
+-              }
+-              child = list_entry(parent->d_subdirs.next, struct dentry,
+-                              d_u.d_child);
+- next_sibling:
+-
+-              /*
+-               * If "child" isn't empty, walk down the tree and
+-               * remove all its descendants first.
+-               */
++              /* perhaps simple_empty(child) makes more sense */
+               if (!list_empty(&child->d_subdirs)) {
+                       mutex_unlock(&parent->d_inode->i_mutex);
+                       parent = child;
+-                      mutex_lock(&parent->d_inode->i_mutex);
+-                      continue;
++                      goto down;
+               }
+-              __debugfs_remove(child, parent);
+-              if (parent->d_subdirs.next == &child->d_u.d_child) {
+-                      /*
+-                       * Try the next sibling.
+-                       */
+-                      if (child->d_u.d_child.next != &parent->d_subdirs) {
+-                              child = list_entry(child->d_u.d_child.next,
+-                                                 struct dentry,
+-                                                 d_u.d_child);
+-                              goto next_sibling;
+-                      }
+-
+-                      /*
+-                       * Avoid infinite loop if we fail to remove
+-                       * one dentry.
+-                       */
+-                      mutex_unlock(&parent->d_inode->i_mutex);
+-                      break;
+-              }
+-              simple_release_fs(&debugfs_mount, &debugfs_mount_count);
++ up:
++              if (!__debugfs_remove(child, parent))
++                      simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+       }
+-      parent = dentry->d_parent;
++      mutex_unlock(&parent->d_inode->i_mutex);
++      child = parent;
++      parent = parent->d_parent;
+       mutex_lock(&parent->d_inode->i_mutex);
+-      __debugfs_remove(dentry, parent);
++
++      if (child != dentry) {
++              next = list_entry(child->d_u.d_child.next, struct dentry,
++                                      d_u.d_child);
++              goto up;
++      }
++
++      if (!__debugfs_remove(child, parent))
++              simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+       mutex_unlock(&parent->d_inode->i_mutex);
+-      simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+ }
+ EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
diff --git a/queue-3.4/ext4-fix-mount-remount-error-messages-for-incompatible-mount-options.patch b/queue-3.4/ext4-fix-mount-remount-error-messages-for-incompatible-mount-options.patch
new file mode 100644 (file)
index 0000000..8958591
--- /dev/null
@@ -0,0 +1,68 @@
+From 6ae6514b33f941d3386da0dfbe2942766eab1577 Mon Sep 17 00:00:00 2001
+From: Piotr Sarna <p.sarna@partner.samsung.com>
+Date: Thu, 8 Aug 2013 23:02:24 -0400
+Subject: ext4: fix mount/remount error messages for incompatible mount options
+
+From: Piotr Sarna <p.sarna@partner.samsung.com>
+
+commit 6ae6514b33f941d3386da0dfbe2942766eab1577 upstream.
+
+Commit 5688978 ("ext4: improve handling of conflicting mount options")
+introduced incorrect messages shown while choosing wrong mount options.
+
+First of all, both cases of incorrect mount options,
+"data=journal,delalloc" and "data=journal,dioread_nolock" result in
+the same error message.
+
+Secondly, the problem above isn't solved for remount option: the
+mismatched parameter is simply ignored.  Moreover, ext4_msg states
+that remount with options "data=journal,delalloc" succeeded, which is
+not true.
+
+To fix it up, I added a simple check after parse_options() call to
+ensure that data=journal and delalloc/dioread_nolock parameters are
+not present at the same time.
+
+Signed-off-by: Piotr Sarna <p.sarna@partner.samsung.com>
+Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c |   17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3232,7 +3232,7 @@ static int ext4_fill_super(struct super_
+               }
+               if (test_opt(sb, DIOREAD_NOLOCK)) {
+                       ext4_msg(sb, KERN_ERR, "can't mount with "
+-                               "both data=journal and delalloc");
++                               "both data=journal and dioread_nolock");
+                       goto failed_mount;
+               }
+               if (test_opt(sb, DELALLOC))
+@@ -4397,6 +4397,21 @@ static int ext4_remount(struct super_blo
+               goto restore_opts;
+       }
++      if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
++              if (test_opt2(sb, EXPLICIT_DELALLOC)) {
++                      ext4_msg(sb, KERN_ERR, "can't mount with "
++                               "both data=journal and delalloc");
++                      err = -EINVAL;
++                      goto restore_opts;
++              }
++              if (test_opt(sb, DIOREAD_NOLOCK)) {
++                      ext4_msg(sb, KERN_ERR, "can't mount with "
++                               "both data=journal and dioread_nolock");
++                      err = -EINVAL;
++                      goto restore_opts;
++              }
++      }
++
+       if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+               ext4_abort(sb, "Abort forced by user");
index db66863f7c18be9544d1b52d04a5047e2dc3cebd..08cd8fbab0a08b47e8a3a76fb44731d2a33e39e1 100644 (file)
@@ -7,3 +7,7 @@ virtio-console-fix-race-in-port_fops_open-and-port-unplug.patch
 virtio-console-clean-up-port-data-immediately-at-time-of-unplug.patch
 virtio-console-fix-raising-sigio-after-port-unplug.patch
 virtio-console-return-enodev-on-all-read-operations-after-unplug.patch
+ext4-fix-mount-remount-error-messages-for-incompatible-mount-options.patch
+cifs-extend-the-buffer-length-enought-for-sprintf-using.patch
+usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch
+debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch
diff --git a/queue-3.4/usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch b/queue-3.4/usb-core-don-t-try-to-reset_device-a-port-that-got-just-disconnected.patch
new file mode 100644 (file)
index 0000000..6352f94
--- /dev/null
@@ -0,0 +1,60 @@
+From 481f2d4f89f87a0baa26147f323380e31cfa7c44 Mon Sep 17 00:00:00 2001
+From: Julius Werner <jwerner@chromium.org>
+Date: Tue, 30 Jul 2013 19:51:20 -0700
+Subject: usb: core: don't try to reset_device() a port that got just disconnected
+
+From: Julius Werner <jwerner@chromium.org>
+
+commit 481f2d4f89f87a0baa26147f323380e31cfa7c44 upstream.
+
+The USB hub driver's event handler contains a check to catch SuperSpeed
+devices that transitioned into the SS.Inactive state and tries to fix
+them with a reset. It decides whether to do a plain hub port reset or
+call the usb_reset_device() function based on whether there was a device
+attached to the port.
+
+However, there are device/hub combinations (found with a JetFlash
+Transcend mass storage stick (8564:1000) on the root hub of an Intel
+LynxPoint PCH) which can transition to the SS.Inactive state on
+disconnect (and stay there long enough for the host to notice). In this
+case, above-mentioned reset check will call usb_reset_device() on the
+stale device data structure. The kernel will send pointless LPM control
+messages to the no longer connected device address and can even cause
+several 5 second khubd stalls on some (buggy?) host controllers, before
+finally accepting the device's fate amongst a flurry of error messages.
+
+This patch makes the choice of reset dependent on the port status that
+has just been read from the hub in addition to the existence of an
+in-kernel data structure for the device, and only proceeds with the more
+extensive reset if both are valid.
+
+Signed-off-by: Julius Werner <jwerner@chromium.org>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3890,7 +3890,8 @@ static void hub_events(void)
+                                       hub->hdev->children[i - 1];
+                               dev_dbg(hub_dev, "warm reset port %d\n", i);
+-                              if (!udev) {
++                              if (!udev || !(portstatus &
++                                              USB_PORT_STAT_CONNECTION)) {
+                                       status = hub_port_reset(hub, i,
+                                                       NULL, HUB_BH_RESET_TIME,
+                                                       true);
+@@ -3900,8 +3901,8 @@ static void hub_events(void)
+                                       usb_lock_device(udev);
+                                       status = usb_reset_device(udev);
+                                       usb_unlock_device(udev);
++                                      connect_change = 0;
+                               }
+-                              connect_change = 0;
+                       }
+                       if (connect_change)