]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Mar 2013 00:45:14 +0000 (16:45 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Mar 2013 00:45:14 +0000 (16:45 -0800)
added patches:
block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch
firewire-add-minor-number-range-check-to-fw_device_init.patch
idr-fix-a-subtle-bug-in-idr_get_next.patch
sysctl-fix-null-checking-in-bin_dn_node_address.patch
xen-blkback-do-not-leak-mode-property.patch
xen-blkback-don-t-trust-the-handle-from-the-frontend.patch

queue-3.4/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch [new file with mode: 0644]
queue-3.4/firewire-add-minor-number-range-check-to-fw_device_init.patch [new file with mode: 0644]
queue-3.4/idr-fix-a-subtle-bug-in-idr_get_next.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/sysctl-fix-null-checking-in-bin_dn_node_address.patch [new file with mode: 0644]
queue-3.4/xen-blkback-do-not-leak-mode-property.patch [new file with mode: 0644]
queue-3.4/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch [new file with mode: 0644]

diff --git a/queue-3.4/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch b/queue-3.4/block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch
new file mode 100644 (file)
index 0000000..ac1146a
--- /dev/null
@@ -0,0 +1,61 @@
+From ce23bba842aee98092225d9576dba47c82352521 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 27 Feb 2013 17:03:56 -0800
+Subject: block: fix synchronization and limit check in blk_alloc_devt()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit ce23bba842aee98092225d9576dba47c82352521 upstream.
+
+idr allocation in blk_alloc_devt() wasn't synchronized against lookup
+and removal, and its limit check was off by one - 1 << MINORBITS is
+the number of minors allowed, not the maximum allowed minor.
+
+Add locking and rename MAX_EXT_DEVT to NR_EXT_DEVT and fix limit
+checking.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Acked-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/genhd.c |   13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -25,7 +25,7 @@ static DEFINE_MUTEX(block_class_lock);
+ struct kobject *block_depr;
+ /* for extended dynamic devt allocation, currently only one major is used */
+-#define MAX_EXT_DEVT          (1 << MINORBITS)
++#define NR_EXT_DEVT           (1 << MINORBITS)
+ /* For extended devt allocation.  ext_devt_mutex prevents look up
+  * results from going away underneath its user.
+@@ -422,19 +422,16 @@ int blk_alloc_devt(struct hd_struct *par
+                       return -ENOMEM;
+               mutex_lock(&ext_devt_mutex);
+               rc = idr_get_new(&ext_devt_idr, part, &idx);
++              if (!rc && idx >= NR_EXT_DEVT) {
++                      idr_remove(&ext_devt_idr, idx);
++                      rc = -EBUSY;
++              }
+               mutex_unlock(&ext_devt_mutex);
+       } while (rc == -EAGAIN);
+       if (rc)
+               return rc;
+-      if (idx > MAX_EXT_DEVT) {
+-              mutex_lock(&ext_devt_mutex);
+-              idr_remove(&ext_devt_idr, idx);
+-              mutex_unlock(&ext_devt_mutex);
+-              return -EBUSY;
+-      }
+-
+       *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx));
+       return 0;
+ }
diff --git a/queue-3.4/firewire-add-minor-number-range-check-to-fw_device_init.patch b/queue-3.4/firewire-add-minor-number-range-check-to-fw_device_init.patch
new file mode 100644 (file)
index 0000000..8248a0b
--- /dev/null
@@ -0,0 +1,36 @@
+From 3bec60d511179853138836ae6e1b61fe34d9235f Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 27 Feb 2013 17:04:04 -0800
+Subject: firewire: add minor number range check to fw_device_init()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 3bec60d511179853138836ae6e1b61fe34d9235f upstream.
+
+fw_device_init() didn't check whether the allocated minor number isn't
+too large.  Fail if it goes overflows MINORBITS.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Suggested-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
+Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firewire/core-device.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/firewire/core-device.c
++++ b/drivers/firewire/core-device.c
+@@ -999,6 +999,10 @@ static void fw_device_init(struct work_s
+       ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ?
+             idr_get_new(&fw_device_idr, device, &minor) :
+             -ENOMEM;
++      if (minor >= 1 << MINORBITS) {
++              idr_remove(&fw_device_idr, minor);
++              minor = -ENOSPC;
++      }
+       up_write(&fw_device_rwsem);
+       if (ret < 0)
diff --git a/queue-3.4/idr-fix-a-subtle-bug-in-idr_get_next.patch b/queue-3.4/idr-fix-a-subtle-bug-in-idr_get_next.patch
new file mode 100644 (file)
index 0000000..0e0f053
--- /dev/null
@@ -0,0 +1,73 @@
+From 6cdae7416a1c45c2ce105a78187d9b7e8feb9e24 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 27 Feb 2013 17:03:34 -0800
+Subject: idr: fix a subtle bug in idr_get_next()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 6cdae7416a1c45c2ce105a78187d9b7e8feb9e24 upstream.
+
+The iteration logic of idr_get_next() is borrowed mostly verbatim from
+idr_for_each().  It walks down the tree looking for the slot matching
+the current ID.  If the matching slot is not found, the ID is
+incremented by the distance of single slot at the given level and
+repeats.
+
+The implementation assumes that during the whole iteration id is aligned
+to the layer boundaries of the level closest to the leaf, which is true
+for all iterations starting from zero or an existing element and thus is
+fine for idr_for_each().
+
+However, idr_get_next() may be given any point and if the starting id
+hits in the middle of a non-existent layer, increment to the next layer
+will end up skipping the same offset into it.  For example, an IDR with
+IDs filled between [64, 127] would look like the following.
+
+          [  0  64 ... ]
+       /----/   |
+       |        |
+      NULL    [ 64 ... 127 ]
+
+If idr_get_next() is called with 63 as the starting point, it will try
+to follow down the pointer from 0.  As it is NULL, it will then try to
+proceed to the next slot in the same level by adding the slot distance
+at that level which is 64 - making the next try 127.  It goes around the
+loop and finds and returns 127 skipping [64, 126].
+
+Note that this bug also triggers in idr_for_each_entry() loop which
+deletes during iteration as deletions can make layers go away leaving
+the iteration with unaligned ID into missing layers.
+
+Fix it by ensuring proceeding to the next slot doesn't carry over the
+unaligned offset - ie.  use round_up(id + 1, slot_distance) instead of
+id += slot_distance.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: David Teigland <teigland@redhat.com>
+Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/idr.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/lib/idr.c
++++ b/lib/idr.c
+@@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int
+                       return p;
+               }
+-              id += 1 << n;
++              /*
++               * Proceed to the next layer at the current level.  Unlike
++               * idr_for_each(), @id isn't guaranteed to be aligned to
++               * layer boundary at this point and adding 1 << n may
++               * incorrectly skip IDs.  Make sure we jump to the
++               * beginning of the next layer using round_up().
++               */
++              id = round_up(id + 1, 1 << n);
+               while (n < fls(id)) {
+                       n += IDR_BITS;
+                       p = *--paa;
index 4d14861d99b2a88439a759be404839d809c891e1..9d57ff8847a708caa14daea01363ff333ccea997 100644 (file)
@@ -13,3 +13,9 @@ ocfs2-fix-possible-use-after-free-with-aio.patch
 ocfs2-fix-ocfs2_init_security_and_acl-to-initialize-acl-correctly.patch
 ocfs2-ac-ac_allow_chain_relink-0-won-t-disable-group-relink.patch
 block-fix-ext_devt_idr-handling.patch
+xen-blkback-do-not-leak-mode-property.patch
+xen-blkback-don-t-trust-the-handle-from-the-frontend.patch
+idr-fix-a-subtle-bug-in-idr_get_next.patch
+block-fix-synchronization-and-limit-check-in-blk_alloc_devt.patch
+firewire-add-minor-number-range-check-to-fw_device_init.patch
+sysctl-fix-null-checking-in-bin_dn_node_address.patch
diff --git a/queue-3.4/sysctl-fix-null-checking-in-bin_dn_node_address.patch b/queue-3.4/sysctl-fix-null-checking-in-bin_dn_node_address.patch
new file mode 100644 (file)
index 0000000..d1a58a9
--- /dev/null
@@ -0,0 +1,36 @@
+From df1778be1a33edffa51d094eeda87c858ded6560 Mon Sep 17 00:00:00 2001
+From: Xi Wang <xi.wang@gmail.com>
+Date: Wed, 27 Feb 2013 17:05:21 -0800
+Subject: sysctl: fix null checking in bin_dn_node_address()
+
+From: Xi Wang <xi.wang@gmail.com>
+
+commit df1778be1a33edffa51d094eeda87c858ded6560 upstream.
+
+The null check of `strchr() + 1' is broken, which is always non-null,
+leading to OOB read.  Instead, check the result of strchr().
+
+Signed-off-by: Xi Wang <xi.wang@gmail.com>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/sysctl_binary.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/sysctl_binary.c
++++ b/kernel/sysctl_binary.c
+@@ -1194,9 +1194,10 @@ static ssize_t bin_dn_node_address(struc
+               /* Convert the decnet address to binary */
+               result = -EIO;
+-              nodep = strchr(buf, '.') + 1;
++              nodep = strchr(buf, '.');
+               if (!nodep)
+                       goto out;
++              ++nodep;
+               area = simple_strtoul(buf, NULL, 10);
+               node = simple_strtoul(nodep, NULL, 10);
diff --git a/queue-3.4/xen-blkback-do-not-leak-mode-property.patch b/queue-3.4/xen-blkback-do-not-leak-mode-property.patch
new file mode 100644 (file)
index 0000000..bbbe677
--- /dev/null
@@ -0,0 +1,113 @@
+From 9d092603cc306ee6edfe917bf9ab8beb5f32d7bc Mon Sep 17 00:00:00 2001
+From: Jan Beulich <JBeulich@suse.com>
+Date: Thu, 20 Dec 2012 10:31:11 +0000
+Subject: xen-blkback: do not leak mode property
+
+From: Jan Beulich <JBeulich@suse.com>
+
+commit 9d092603cc306ee6edfe917bf9ab8beb5f32d7bc upstream.
+
+"be->mode" is obtained from xenbus_read(), which does a kmalloc() for
+the message body. The short string is never released, so do it along
+with freeing "be" itself, and make sure the string isn't kept when
+backend_changed() doesn't complete successfully (which made it
+desirable to slightly re-structure that function, so that the error
+cleanup can be done in one place).
+
+Reported-by: Olaf Hering <olaf@aepfle.de>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/xen-blkback/xenbus.c |   49 ++++++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 25 deletions(-)
+
+--- a/drivers/block/xen-blkback/xenbus.c
++++ b/drivers/block/xen-blkback/xenbus.c
+@@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbu
+               be->blkif = NULL;
+       }
++      kfree(be->mode);
+       kfree(be);
+       dev_set_drvdata(&dev->dev, NULL);
+       return 0;
+@@ -502,6 +503,7 @@ static void backend_changed(struct xenbu
+               = container_of(watch, struct backend_info, backend_watch);
+       struct xenbus_device *dev = be->dev;
+       int cdrom = 0;
++      unsigned long handle;
+       char *device_type;
+       DPRINTK("");
+@@ -521,10 +523,10 @@ static void backend_changed(struct xenbu
+               return;
+       }
+-      if ((be->major || be->minor) &&
+-          ((be->major != major) || (be->minor != minor))) {
+-              pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n",
+-                      be->major, be->minor, major, minor);
++      if (be->major | be->minor) {
++              if (be->major != major || be->minor != minor)
++                      pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n",
++                              be->major, be->minor, major, minor);
+               return;
+       }
+@@ -542,36 +544,33 @@ static void backend_changed(struct xenbu
+               kfree(device_type);
+       }
+-      if (be->major == 0 && be->minor == 0) {
+-              /* Front end dir is a number, which is used as the handle. */
++      /* Front end dir is a number, which is used as the handle. */
++      err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
++      if (err)
++              return;
+-              char *p = strrchr(dev->otherend, '/') + 1;
+-              long handle;
+-              err = strict_strtoul(p, 0, &handle);
+-              if (err)
+-                      return;
++      be->major = major;
++      be->minor = minor;
+-              be->major = major;
+-              be->minor = minor;
+-
+-              err = xen_vbd_create(be->blkif, handle, major, minor,
+-                               (NULL == strchr(be->mode, 'w')), cdrom);
+-              if (err) {
+-                      be->major = 0;
+-                      be->minor = 0;
+-                      xenbus_dev_fatal(dev, err, "creating vbd structure");
+-                      return;
+-              }
++      err = xen_vbd_create(be->blkif, handle, major, minor,
++                           !strchr(be->mode, 'w'), cdrom);
++      if (err)
++              xenbus_dev_fatal(dev, err, "creating vbd structure");
++      else {
+               err = xenvbd_sysfs_addif(dev);
+               if (err) {
+                       xen_vbd_free(&be->blkif->vbd);
+-                      be->major = 0;
+-                      be->minor = 0;
+                       xenbus_dev_fatal(dev, err, "creating sysfs entries");
+-                      return;
+               }
++      }
++      if (err) {
++              kfree(be->mode);
++              be->mode = NULL;
++              be->major = 0;
++              be->minor = 0;
++      } else {
+               /* We're potentially connected now */
+               xen_update_blkif_status(be->blkif);
+       }
diff --git a/queue-3.4/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch b/queue-3.4/xen-blkback-don-t-trust-the-handle-from-the-frontend.patch
new file mode 100644 (file)
index 0000000..1a9c4a8
--- /dev/null
@@ -0,0 +1,38 @@
+From 01c681d4c70d64cb72142a2823f27c4146a02e63 Mon Sep 17 00:00:00 2001
+From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Date: Wed, 16 Jan 2013 11:36:23 -0500
+Subject: xen/blkback: Don't trust the handle from the frontend.
+
+From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+
+commit 01c681d4c70d64cb72142a2823f27c4146a02e63 upstream.
+
+The 'handle' is the device that the request is from. For the life-time
+of the ring we copy it from a request to a response so that the frontend
+is not surprised by it. But we do not need it - when we start processing
+I/Os we have our own 'struct phys_req' which has only most essential
+information about the request. In fact the 'vbd_translate' ends up
+over-writing the preq.dev with a value from the backend.
+
+This assignment of preq.dev with the 'handle' value is superfluous
+so lets not do it.
+
+Acked-by: Jan Beulich <jbeulich@suse.com>
+Acked-by: Ian Campbell <ian.campbell@citrix.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/xen-blkback/blkback.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/block/xen-blkback/blkback.c
++++ b/drivers/block/xen-blkback/blkback.c
+@@ -623,7 +623,6 @@ static int dispatch_rw_block_io(struct x
+               goto fail_response;
+       }
+-      preq.dev           = req->u.rw.handle;
+       preq.sector_number = req->u.rw.sector_number;
+       preq.nr_sects      = 0;