[PATCH] fix broken lib/genalloc.c

From: Chris Humbert
Date: Thu Nov 24 2005 - 08:31:30 EST


genalloc improperly stores the size of freed chunks, allocates
overlapping memory regions, and oopses after its in-band data is
overwritten. Jes Sorensen's original patch to LKML used:

> + s = (1 << ALLOC_MIN_SHIFT);
> + while (size > s) {
> + s <<= 1;
> + i++;
> + }

After Andrew Morton suggested roundup_pow_of_two(), Jes changed
it to:

> + size = max(size, 1 << ALLOC_MIN_SHIFT);
> + s = roundup_pow_of_two(size);

but this does not set 'i'. I have verified that genalloc with
the attached patch works correctly.

Chris Humbert



[PATCH] fix broken lib/genalloc.c

genalloc improperly stores the sizes of freed chunks, allocates
overlapping memory regions, and oopses after its in-band data is
overwritten.

Signed-off-by: Chris Humbert <mahadri-kernel@xxxxxxxxxx>

diff --git a/lib/genalloc.c b/lib/genalloc.c
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -95,12 +95,10 @@ unsigned long gen_pool_alloc(struct gen_
if (size > max_chunk_size)
return 0;

- i = 0;
-
size = max(size, 1 << ALLOC_MIN_SHIFT);
- s = roundup_pow_of_two(size);
-
- j = i;
+ i = fls(size - 1);
+ s = 1 << i;
+ j = i -= ALLOC_MIN_SHIFT;

spin_lock_irqsave(&poolp->lock, flags);
while (!h[j].next) {
@@ -153,10 +151,10 @@ void gen_pool_free(struct gen_pool *pool
if (size > max_chunk_size)
return;

- i = 0;
-
size = max(size, 1 << ALLOC_MIN_SHIFT);
- s = roundup_pow_of_two(size);
+ i = fls(size - 1);
+ s = 1 << i;
+ i -= ALLOC_MIN_SHIFT;

a = ptr;

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