bitmap: fix end condition in bitmap_find_free_region
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Mar 2009 02:32:51 +0000 (19:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Mar 2009 02:32:51 +0000 (19:32 -0700)
Guennadi Liakhovetski noticed that the end condition for the loop in
bitmap_find_free_region() is wrong, and the "return if error" was also
using the wrong conditional that would only trigger if the bitmap was an
exact multiple of the allocation size, which is not necessarily the case
with dma_alloc_from_coherent().

Such a failure would end up in bitmap_find_free_region() accessing
beyond the end of the bitmap.

Reported-by: Guennadi Liakhovetski <lg@denx.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
lib/bitmap.c

index 1338469ac849cb230fc8f1e74441ece4a6cfd58c..35a1f7ff414988d86c6c081d7bbf3671733a15d6 100644 (file)
@@ -948,15 +948,15 @@ done:
  */
 int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
 {
-       int pos;                /* scans bitmap by regions of size order */
+       int pos, end;           /* scans bitmap by regions of size order */
 
-       for (pos = 0; pos < bits; pos += (1 << order))
-               if (__reg_op(bitmap, pos, order, REG_OP_ISFREE))
-                       break;
-       if (pos == bits)
-               return -ENOMEM;
-       __reg_op(bitmap, pos, order, REG_OP_ALLOC);
-       return pos;
+       for (pos = 0 ; (end = pos + (1 << order)) <= bits; pos = end) {
+               if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
+                       continue;
+               __reg_op(bitmap, pos, order, REG_OP_ALLOC);
+               return pos;
+       }
+       return -ENOMEM;
 }
 EXPORT_SYMBOL(bitmap_find_free_region);