3.5.7.6 -stable review patch.  If anyone has any objections, please let me know.

------------------

From: T Makphaibulchoke <t...@hp.com>

commit 4965f5667f36a95b41cda6638875bc992bd7d18b upstream.

Using a recursive call add a non-conflicting region in
__reserve_region_with_split() could result in a stack overflow in the case
that the recursive calls are too deep.  Convert the recursive calls to an
iterative loop to avoid the problem.

Tested on a machine containing 135 regions.  The kernel no longer panicked
with stack overflow.

Also tested with code arbitrarily adding regions with no conflict,
embedding two consecutive conflicts and embedding two non-consecutive
conflicts.

Signed-off-by: T Makphaibulchoke <t...@hp.com>
Reviewed-by: Ram Pai <linux...@us.ibm.com>
Cc: Paul Gortmaker <paul.gortma...@gmail.com>
Cc: Wei Yang <weiy...@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <a...@linux-foundation.org>
Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
Cc: Jiri Slaby <jsl...@suse.cz>
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesin...@canonical.com>
---
 kernel/resource.c |   50 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/kernel/resource.c b/kernel/resource.c
index e1d2b8e..7de982e 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -758,6 +758,7 @@ static void __init __reserve_region_with_split(struct 
resource *root,
        struct resource *parent = root;
        struct resource *conflict;
        struct resource *res = kzalloc(sizeof(*res), GFP_ATOMIC);
+       struct resource *next_res = NULL;
 
        if (!res)
                return;
@@ -767,21 +768,46 @@ static void __init __reserve_region_with_split(struct 
resource *root,
        res->end = end;
        res->flags = IORESOURCE_BUSY;
 
-       conflict = __request_resource(parent, res);
-       if (!conflict)
-               return;
+       while (1) {
 
-       /* failed, split and try again */
-       kfree(res);
+               conflict = __request_resource(parent, res);
+               if (!conflict) {
+                       if (!next_res)
+                               break;
+                       res = next_res;
+                       next_res = NULL;
+                       continue;
+               }
 
-       /* conflict covered whole area */
-       if (conflict->start <= start && conflict->end >= end)
-               return;
+               /* conflict covered whole area */
+               if (conflict->start <= res->start &&
+                               conflict->end >= res->end) {
+                       kfree(res);
+                       WARN_ON(next_res);
+                       break;
+               }
+
+               /* failed, split and try again */
+               if (conflict->start > res->start) {
+                       end = res->end;
+                       res->end = conflict->start - 1;
+                       if (conflict->end < end) {
+                               next_res = kzalloc(sizeof(*next_res),
+                                               GFP_ATOMIC);
+                               if (!next_res) {
+                                       kfree(res);
+                                       break;
+                               }
+                               next_res->name = name;
+                               next_res->start = conflict->end + 1;
+                               next_res->end = end;
+                               next_res->flags = IORESOURCE_BUSY;
+                       }
+               } else {
+                       res->start = conflict->end + 1;
+               }
+       }
 
-       if (conflict->start > start)
-               __reserve_region_with_split(root, start, conflict->start-1, 
name);
-       if (conflict->end < end)
-               __reserve_region_with_split(root, conflict->end+1, end, name);
 }
 
 void __init reserve_region_with_split(struct resource *root,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to