]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Nov 2014 00:58:54 +0000 (09:58 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Nov 2014 00:58:54 +0000 (09:58 +0900)
added patches:
btrfs-fix-kfree-on-list_head-in-btrfs_lookup_csums_range-error-cleanup.patch
mm-page_alloc-fix-zone-allocation-fairness-on-up.patch
of-fix-overflow-bug-in-string-property-parsing-functions.patch

queue-3.14/btrfs-fix-kfree-on-list_head-in-btrfs_lookup_csums_range-error-cleanup.patch [new file with mode: 0644]
queue-3.14/mm-page_alloc-fix-zone-allocation-fairness-on-up.patch [new file with mode: 0644]
queue-3.14/of-fix-overflow-bug-in-string-property-parsing-functions.patch [new file with mode: 0644]
queue-3.14/series

diff --git a/queue-3.14/btrfs-fix-kfree-on-list_head-in-btrfs_lookup_csums_range-error-cleanup.patch b/queue-3.14/btrfs-fix-kfree-on-list_head-in-btrfs_lookup_csums_range-error-cleanup.patch
new file mode 100644 (file)
index 0000000..d68b1d1
--- /dev/null
@@ -0,0 +1,36 @@
+From 6e5aafb27419f32575b27ef9d6a31e5d54661aca Mon Sep 17 00:00:00 2001
+From: Chris Mason <clm@fb.com>
+Date: Tue, 4 Nov 2014 06:59:04 -0800
+Subject: Btrfs: fix kfree on list_head in btrfs_lookup_csums_range error cleanup
+
+From: Chris Mason <clm@fb.com>
+
+commit 6e5aafb27419f32575b27ef9d6a31e5d54661aca upstream.
+
+If we hit any errors in btrfs_lookup_csums_range, we'll loop through all
+the csums we allocate and free them.  But the code was using list_entry
+incorrectly, and ended up trying to free the on-stack list_head instead.
+
+This bug came from commit 0678b6185
+
+btrfs: Don't BUG_ON kzalloc error in btrfs_lookup_csums_range()
+
+Signed-off-by: Chris Mason <clm@fb.com>
+Reported-by: Erik Berg <btrfs@slipsprogrammoer.no>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/file-item.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/file-item.c
++++ b/fs/btrfs/file-item.c
+@@ -423,7 +423,7 @@ int btrfs_lookup_csums_range(struct btrf
+       ret = 0;
+ fail:
+       while (ret < 0 && !list_empty(&tmplist)) {
+-              sums = list_entry(&tmplist, struct btrfs_ordered_sum, list);
++              sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list);
+               list_del(&sums->list);
+               kfree(sums);
+       }
diff --git a/queue-3.14/mm-page_alloc-fix-zone-allocation-fairness-on-up.patch b/queue-3.14/mm-page_alloc-fix-zone-allocation-fairness-on-up.patch
new file mode 100644 (file)
index 0000000..11938fa
--- /dev/null
@@ -0,0 +1,61 @@
+From abe5f972912d086c080be4bde67750630b6fb38b Mon Sep 17 00:00:00 2001
+From: Johannes Weiner <hannes@cmpxchg.org>
+Date: Thu, 2 Oct 2014 16:21:10 -0700
+Subject: mm: page_alloc: fix zone allocation fairness on UP
+
+From: Johannes Weiner <hannes@cmpxchg.org>
+
+commit abe5f972912d086c080be4bde67750630b6fb38b upstream.
+
+The zone allocation batches can easily underflow due to higher-order
+allocations or spills to remote nodes.  On SMP that's fine, because
+underflows are expected from concurrency and dealt with by returning 0.
+But on UP, zone_page_state will just return a wrapped unsigned long,
+which will get past the <= 0 check and then consider the zone eligible
+until its watermarks are hit.
+
+Commit 3a025760fc15 ("mm: page_alloc: spill to remote nodes before
+waking kswapd") already made the counter-resetting use
+atomic_long_read() to accomodate underflows from remote spills, but it
+didn't go all the way with it.
+
+Make it clear that these batches are expected to go negative regardless
+of concurrency, and use atomic_long_read() everywhere.
+
+Fixes: 81c0a2bb515f ("mm: page_alloc: fair zone allocator policy")
+Reported-by: Vlastimil Babka <vbabka@suse.cz>
+Reported-by: Leon Romanovsky <leon@leon.nu>
+Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
+Acked-by: Mel Gorman <mgorman@suse.de>
+Cc: <stable@vger.kernel.org>   [3.12+]
+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>
+
+---
+ mm/page_alloc.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1957,7 +1957,7 @@ zonelist_scan:
+               if (alloc_flags & ALLOC_FAIR) {
+                       if (!zone_local(preferred_zone, zone))
+                               continue;
+-                      if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0)
++                      if (atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]) <= 0)
+                               continue;
+               }
+               /*
+@@ -5670,9 +5670,8 @@ static void __setup_per_zone_wmarks(void
+               zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1);
+               __mod_zone_page_state(zone, NR_ALLOC_BATCH,
+-                                    high_wmark_pages(zone) -
+-                                    low_wmark_pages(zone) -
+-                                    zone_page_state(zone, NR_ALLOC_BATCH));
++                      high_wmark_pages(zone) - low_wmark_pages(zone) -
++                      atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]));
+               setup_zone_migrate_reserve(zone);
+               spin_unlock_irqrestore(&zone->lock, flags);
diff --git a/queue-3.14/of-fix-overflow-bug-in-string-property-parsing-functions.patch b/queue-3.14/of-fix-overflow-bug-in-string-property-parsing-functions.patch
new file mode 100644 (file)
index 0000000..66a85a8
--- /dev/null
@@ -0,0 +1,373 @@
+From a87fa1d81a9fb5e9adca9820e16008c40ad09f33 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Mon, 3 Nov 2014 15:15:35 +0000
+Subject: of: Fix overflow bug in string property parsing functions
+
+From: Grant Likely <grant.likely@linaro.org>
+
+commit a87fa1d81a9fb5e9adca9820e16008c40ad09f33 upstream.
+
+The string property read helpers will run off the end of the buffer if
+it is handed a malformed string property. Rework the parsers to make
+sure that doesn't happen. At the same time add new test cases to make
+sure the functions behave themselves.
+
+The original implementations of of_property_read_string_index() and
+of_property_count_strings() both open-coded the same block of parsing
+code, each with it's own subtly different bugs. The fix here merges
+functions into a single helper and makes the original functions static
+inline wrappers around the helper.
+
+One non-bugfix aspect of this patch is the addition of a new wrapper,
+of_property_read_string_array(). The new wrapper is needed by the
+device_properties feature that Rafael is working on and planning to
+merge for v3.19. The implementation is identical both with and without
+the new static inline wrapper, so it just got left in to reduce the
+churn on the header file.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
+Cc: Rob Herring <robh+dt@kernel.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Darren Hart <darren.hart@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/of/base.c                           |   88 +++++++---------------------
+ drivers/of/selftest.c                       |   64 ++++++++++++++++++--
+ drivers/of/testcase-data/tests-phandle.dtsi |    2 
+ include/linux/of.h                          |   84 ++++++++++++++++++++++----
+ 4 files changed, 153 insertions(+), 85 deletions(-)
+
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1117,52 +1117,6 @@ int of_property_read_string(struct devic
+ EXPORT_SYMBOL_GPL(of_property_read_string);
+ /**
+- * of_property_read_string_index - Find and read a string from a multiple
+- * strings property.
+- * @np:               device node from which the property value is to be read.
+- * @propname: name of the property to be searched.
+- * @index:    index of the string in the list of strings
+- * @out_string:       pointer to null terminated return string, modified only if
+- *            return value is 0.
+- *
+- * Search for a property in a device tree node and retrieve a null
+- * terminated string value (pointer to data, not a copy) in the list of strings
+- * contained in that property.
+- * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+- * property does not have a value, and -EILSEQ if the string is not
+- * null-terminated within the length of the property data.
+- *
+- * The out_string pointer is modified only if a valid string can be decoded.
+- */
+-int of_property_read_string_index(struct device_node *np, const char *propname,
+-                                int index, const char **output)
+-{
+-      struct property *prop = of_find_property(np, propname, NULL);
+-      int i = 0;
+-      size_t l = 0, total = 0;
+-      const char *p;
+-
+-      if (!prop)
+-              return -EINVAL;
+-      if (!prop->value)
+-              return -ENODATA;
+-      if (strnlen(prop->value, prop->length) >= prop->length)
+-              return -EILSEQ;
+-
+-      p = prop->value;
+-
+-      for (i = 0; total < prop->length; total += l, p += l) {
+-              l = strlen(p) + 1;
+-              if (i++ == index) {
+-                      *output = p;
+-                      return 0;
+-              }
+-      }
+-      return -ENODATA;
+-}
+-EXPORT_SYMBOL_GPL(of_property_read_string_index);
+-
+-/**
+  * of_property_match_string() - Find string in a list and return index
+  * @np: pointer to node containing string list property
+  * @propname: string list property name
+@@ -1188,7 +1142,7 @@ int of_property_match_string(struct devi
+       end = p + prop->length;
+       for (i = 0; p < end; i++, p += l) {
+-              l = strlen(p) + 1;
++              l = strnlen(p, end - p) + 1;
+               if (p + l > end)
+                       return -EILSEQ;
+               pr_debug("comparing %s with %s\n", string, p);
+@@ -1200,39 +1154,41 @@ int of_property_match_string(struct devi
+ EXPORT_SYMBOL_GPL(of_property_match_string);
+ /**
+- * of_property_count_strings - Find and return the number of strings from a
+- * multiple strings property.
++ * of_property_read_string_util() - Utility helper for parsing string properties
+  * @np:               device node from which the property value is to be read.
+  * @propname: name of the property to be searched.
++ * @out_strs: output array of string pointers.
++ * @sz:               number of array elements to read.
++ * @skip:     Number of strings to skip over at beginning of list.
+  *
+- * Search for a property in a device tree node and retrieve the number of null
+- * terminated string contain in it. Returns the number of strings on
+- * success, -EINVAL if the property does not exist, -ENODATA if property
+- * does not have a value, and -EILSEQ if the string is not null-terminated
+- * within the length of the property data.
++ * Don't call this function directly. It is a utility helper for the
++ * of_property_read_string*() family of functions.
+  */
+-int of_property_count_strings(struct device_node *np, const char *propname)
++int of_property_read_string_helper(struct device_node *np, const char *propname,
++                                 const char **out_strs, size_t sz, int skip)
+ {
+       struct property *prop = of_find_property(np, propname, NULL);
+-      int i = 0;
+-      size_t l = 0, total = 0;
+-      const char *p;
++      int l = 0, i = 0;
++      const char *p, *end;
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+-      if (strnlen(prop->value, prop->length) >= prop->length)
+-              return -EILSEQ;
+-
+       p = prop->value;
++      end = p + prop->length;
+-      for (i = 0; total < prop->length; total += l, p += l, i++)
+-              l = strlen(p) + 1;
+-
+-      return i;
++      for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
++              l = strnlen(p, end - p) + 1;
++              if (p + l > end)
++                      return -EILSEQ;
++              if (out_strs && i >= skip)
++                      *out_strs++ = p;
++      }
++      i -= skip;
++      return i <= 0 ? -ENODATA : i;
+ }
+-EXPORT_SYMBOL_GPL(of_property_count_strings);
++EXPORT_SYMBOL_GPL(of_property_read_string_helper);
+ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
+ {
+--- a/drivers/of/selftest.c
++++ b/drivers/of/selftest.c
+@@ -132,8 +132,9 @@ static void __init of_selftest_parse_pha
+       selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
+ }
+-static void __init of_selftest_property_match_string(void)
++static void __init of_selftest_property_string(void)
+ {
++      const char *strings[4];
+       struct device_node *np;
+       int rc;
+@@ -150,13 +151,66 @@ static void __init of_selftest_property_
+       rc = of_property_match_string(np, "phandle-list-names", "third");
+       selftest(rc == 2, "third expected:0 got:%i\n", rc);
+       rc = of_property_match_string(np, "phandle-list-names", "fourth");
+-      selftest(rc == -ENODATA, "unmatched string; rc=%i", rc);
++      selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc);
+       rc = of_property_match_string(np, "missing-property", "blah");
+-      selftest(rc == -EINVAL, "missing property; rc=%i", rc);
++      selftest(rc == -EINVAL, "missing property; rc=%i\n", rc);
+       rc = of_property_match_string(np, "empty-property", "blah");
+-      selftest(rc == -ENODATA, "empty property; rc=%i", rc);
++      selftest(rc == -ENODATA, "empty property; rc=%i\n", rc);
+       rc = of_property_match_string(np, "unterminated-string", "blah");
+-      selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
++      selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
++
++      /* of_property_count_strings() tests */
++      rc = of_property_count_strings(np, "string-property");
++      selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
++      rc = of_property_count_strings(np, "phandle-list-names");
++      selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
++      rc = of_property_count_strings(np, "unterminated-string");
++      selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
++      rc = of_property_count_strings(np, "unterminated-string-list");
++      selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
++
++      /* of_property_read_string_index() tests */
++      rc = of_property_read_string_index(np, "string-property", 0, strings);
++      selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc);
++      strings[0] = NULL;
++      rc = of_property_read_string_index(np, "string-property", 1, strings);
++      selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
++      rc = of_property_read_string_index(np, "phandle-list-names", 0, strings);
++      selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
++      rc = of_property_read_string_index(np, "phandle-list-names", 1, strings);
++      selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc);
++      rc = of_property_read_string_index(np, "phandle-list-names", 2, strings);
++      selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc);
++      strings[0] = NULL;
++      rc = of_property_read_string_index(np, "phandle-list-names", 3, strings);
++      selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
++      strings[0] = NULL;
++      rc = of_property_read_string_index(np, "unterminated-string", 0, strings);
++      selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
++      rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings);
++      selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
++      strings[0] = NULL;
++      rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */
++      selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
++      strings[1] = NULL;
++
++      /* of_property_read_string_array() tests */
++      rc = of_property_read_string_array(np, "string-property", strings, 4);
++      selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
++      rc = of_property_read_string_array(np, "phandle-list-names", strings, 4);
++      selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
++      rc = of_property_read_string_array(np, "unterminated-string", strings, 4);
++      selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
++      /* -- An incorrectly formed string should cause a failure */
++      rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4);
++      selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
++      /* -- parsing the correctly formed strings should still work: */
++      strings[2] = NULL;
++      rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2);
++      selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc);
++      strings[1] = NULL;
++      rc = of_property_read_string_array(np, "phandle-list-names", strings, 1);
++      selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]);
+ }
+ static void __init of_selftest_parse_interrupts(void)
+--- a/drivers/of/testcase-data/tests-phandle.dtsi
++++ b/drivers/of/testcase-data/tests-phandle.dtsi
+@@ -32,7 +32,9 @@
+                               phandle-list-bad-args = <&provider2 1 0>,
+                                                       <&provider3 0>;
+                               empty-property;
++                              string-property = "foobar";
+                               unterminated-string = [40 41 42 43];
++                              unterminated-string-list = "first", "second", [40 41 42 43];
+                       };
+               };
+       };
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -215,14 +215,12 @@ extern int of_property_read_u64(const st
+ extern int of_property_read_string(struct device_node *np,
+                                  const char *propname,
+                                  const char **out_string);
+-extern int of_property_read_string_index(struct device_node *np,
+-                                       const char *propname,
+-                                       int index, const char **output);
+ extern int of_property_match_string(struct device_node *np,
+                                   const char *propname,
+                                   const char *string);
+-extern int of_property_count_strings(struct device_node *np,
+-                                   const char *propname);
++extern int of_property_read_string_helper(struct device_node *np,
++                                            const char *propname,
++                                            const char **out_strs, size_t sz, int index);
+ extern int of_device_is_compatible(const struct device_node *device,
+                                  const char *);
+ extern int of_device_is_available(const struct device_node *device);
+@@ -422,15 +420,9 @@ static inline int of_property_read_strin
+       return -ENOSYS;
+ }
+-static inline int of_property_read_string_index(struct device_node *np,
+-                                              const char *propname, int index,
+-                                              const char **out_string)
+-{
+-      return -ENOSYS;
+-}
+-
+-static inline int of_property_count_strings(struct device_node *np,
+-                                          const char *propname)
++static inline int of_property_read_string_helper(struct device_node *np,
++                                               const char *propname,
++                                               const char **out_strs, size_t sz, int index)
+ {
+       return -ENOSYS;
+ }
+@@ -536,6 +528,70 @@ static inline struct device_node *of_fin
+ }
+ /**
++ * of_property_read_string_array() - Read an array of strings from a multiple
++ * strings property.
++ * @np:               device node from which the property value is to be read.
++ * @propname: name of the property to be searched.
++ * @out_strs: output array of string pointers.
++ * @sz:               number of array elements to read.
++ *
++ * Search for a property in a device tree node and retrieve a list of
++ * terminated string values (pointer to data, not a copy) in that property.
++ *
++ * If @out_strs is NULL, the number of strings in the property is returned.
++ */
++static inline int of_property_read_string_array(struct device_node *np,
++                                              const char *propname, const char **out_strs,
++                                              size_t sz)
++{
++      return of_property_read_string_helper(np, propname, out_strs, sz, 0);
++}
++
++/**
++ * of_property_count_strings() - Find and return the number of strings from a
++ * multiple strings property.
++ * @np:               device node from which the property value is to be read.
++ * @propname: name of the property to be searched.
++ *
++ * Search for a property in a device tree node and retrieve the number of null
++ * terminated string contain in it. Returns the number of strings on
++ * success, -EINVAL if the property does not exist, -ENODATA if property
++ * does not have a value, and -EILSEQ if the string is not null-terminated
++ * within the length of the property data.
++ */
++static inline int of_property_count_strings(struct device_node *np,
++                                          const char *propname)
++{
++      return of_property_read_string_helper(np, propname, NULL, 0, 0);
++}
++
++/**
++ * of_property_read_string_index() - Find and read a string from a multiple
++ * strings property.
++ * @np:               device node from which the property value is to be read.
++ * @propname: name of the property to be searched.
++ * @index:    index of the string in the list of strings
++ * @out_string:       pointer to null terminated return string, modified only if
++ *            return value is 0.
++ *
++ * Search for a property in a device tree node and retrieve a null
++ * terminated string value (pointer to data, not a copy) in the list of strings
++ * contained in that property.
++ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
++ * property does not have a value, and -EILSEQ if the string is not
++ * null-terminated within the length of the property data.
++ *
++ * The out_string pointer is modified only if a valid string can be decoded.
++ */
++static inline int of_property_read_string_index(struct device_node *np,
++                                              const char *propname,
++                                              int index, const char **output)
++{
++      int rc = of_property_read_string_helper(np, propname, output, 1, index);
++      return rc < 0 ? rc : 0;
++}
++
++/**
+  * of_property_read_bool - Findfrom a property
+  * @np:               device node from which the property value is to be read.
+  * @propname: name of the property to be searched.
index bb2cd770ee50c4d906f97d340fd16436f76e43c9..9a07b50f843550938d9160a54da4e78e9cfcfd83 100644 (file)
@@ -198,3 +198,6 @@ powerpc-use-device_online-offline-instead-of-cpu_up-down.patch
 regulator-max77693-fix-use-of-uninitialized-regulator-config.patch
 i2c-at91-don-t-account-as-iowait.patch
 sysfs-driver-core-fix-glue-dir-race-condition-by-gdp_mutex.patch
+of-fix-overflow-bug-in-string-property-parsing-functions.patch
+btrfs-fix-kfree-on-list_head-in-btrfs_lookup_csums_range-error-cleanup.patch
+mm-page_alloc-fix-zone-allocation-fairness-on-up.patch