
From: Prasanna Meda <pmeda@akamai.com>

- Race in mempool_resize: memcpy can copy at the end of the kmalloced
  elements.

- When new_min_nr is same as min_nr, instead of reallocate and copy, just
  return, changed '<' to '<='.

- Changed while condition to the same sense of if condition from '>' to
  '<'; it is easy to think with only one of the left and right brains at a
  time.

Signed-off-by: Prasanna Meda <pmeda@akamai.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/mm/mempool.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff -puN mm/mempool.c~mempool-protect-buffer-overflow-in-mempool_resize mm/mempool.c
--- 25/mm/mempool.c~mempool-protect-buffer-overflow-in-mempool_resize	2005-03-07 20:41:22.000000000 -0800
+++ 25-akpm/mm/mempool.c	2005-03-07 20:41:22.000000000 -0800
@@ -114,8 +114,8 @@ int mempool_resize(mempool_t *pool, int 
 	BUG_ON(new_min_nr <= 0);
 
 	spin_lock_irqsave(&pool->lock, flags);
-	if (new_min_nr < pool->min_nr) {
-		while (pool->curr_nr > new_min_nr) {
+	if (new_min_nr <= pool->min_nr) {
+		while (new_min_nr < pool->curr_nr) {
 			element = remove_element(pool);
 			spin_unlock_irqrestore(&pool->lock, flags);
 			pool->free(element, pool->pool_data);
@@ -132,6 +132,12 @@ int mempool_resize(mempool_t *pool, int 
 		return -ENOMEM;
 
 	spin_lock_irqsave(&pool->lock, flags);
+	if (unlikely(new_min_nr <= pool->min_nr)) {
+		/* Raced, other resize will do our work */
+		spin_unlock_irqrestore(&pool->lock, flags);
+		kfree(new_elements);
+		goto out;
+	}
 	memcpy(new_elements, pool->elements,
 			pool->curr_nr * sizeof(*new_elements));
 	kfree(pool->elements);
@@ -149,7 +155,7 @@ int mempool_resize(mempool_t *pool, int 
 		} else {
 			spin_unlock_irqrestore(&pool->lock, flags);
 			pool->free(element, pool->pool_data);	/* Raced */
-			spin_lock_irqsave(&pool->lock, flags);
+			goto out;
 		}
 	}
 out_unlock:
_
