aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/resource.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2010-10-26 17:41:28 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-10-26 18:33:28 -0400
commita1862e31079149a52b6223776228c3aee493d4a7 (patch)
treef70f7e3f33f63dcf77428b745f0dd01ecbee8e24 /kernel/resource.c
parent6909ba14c25b4db6be2ff89f4fa0fac2d70151a0 (diff)
resources: handle overflow when aligning start of available area
If tmp.start is near ~0, ALIGN(tmp.start) may overflow, which would make us think there's more available space than there really is. We would likely return something that conflicts with a previous resource, which would cause a failure when allocate_resource() requests the newly- allocated region. Reference: https://bugzilla.redhat.com/show_bug.cgi?id=646027 Reported-by: Fabrice Bellet <fabrice@bellet.info> Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r--kernel/resource.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/kernel/resource.c b/kernel/resource.c
index 89d50412508c..e15b922d4ba4 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -392,7 +392,7 @@ static int find_resource(struct resource *root, struct resource *new,
392 void *alignf_data) 392 void *alignf_data)
393{ 393{
394 struct resource *this = root->child; 394 struct resource *this = root->child;
395 struct resource tmp = *new, alloc; 395 struct resource tmp = *new, avail, alloc;
396 396
397 tmp.start = root->start; 397 tmp.start = root->start;
398 /* 398 /*
@@ -410,14 +410,19 @@ static int find_resource(struct resource *root, struct resource *new,
410 tmp.end = root->end; 410 tmp.end = root->end;
411 411
412 resource_clip(&tmp, min, max); 412 resource_clip(&tmp, min, max);
413 tmp.start = ALIGN(tmp.start, align);
414 413
415 alloc.start = alignf(alignf_data, &tmp, size, align); 414 /* Check for overflow after ALIGN() */
416 alloc.end = alloc.start + size - 1; 415 avail = *new;
417 if (resource_contains(&tmp, &alloc)) { 416 avail.start = ALIGN(tmp.start, align);
418 new->start = alloc.start; 417 avail.end = tmp.end;
419 new->end = alloc.end; 418 if (avail.start >= tmp.start) {
420 return 0; 419 alloc.start = alignf(alignf_data, &avail, size, align);
420 alloc.end = alloc.start + size - 1;
421 if (resource_contains(&avail, &alloc)) {
422 new->start = alloc.start;
423 new->end = alloc.end;
424 return 0;
425 }
421 } 426 }
422 if (!this) 427 if (!this)
423 break; 428 break;