summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShashank Mohan Jain <jain.sm@gmail.com>2026-09-26 06:56:50 +0530
committerYury Norov <ynorov@nvidia.com>2026-09-26 10:21:23 -0400
commitd075c4dc0b3c8ed91a4f67ebdf3384aa59fd4fbb (patch)
tree1316c797acd9c4238113e2b4c5a2d7aa0a5ef1f2
parentf2c318d812f9b108c4808342ea135e2788c5fd6e (diff)
downloadlinux-next-d075c4dc0b3c8ed91a4f67ebdf3384aa59fd4fbb.tar.gz
linux-next-d075c4dc0b3c8ed91a4f67ebdf3384aa59fd4fbb.zip
bitmap: bitmap_parselist(): don't wrap around on a huge group size
In the "range:used/group" form bitmap_set_region() walks the range with for (start = r->start; start <= r->end; start += r->group_len) where all values are unsigned int. bitmap_getnum() accepts any group size up to UINT_MAX, and bitmap_check_region() only requires it to be non-zero and at least the used size. If start + group_len exceeds UINT_MAX, start wraps around to a small value that is still <= end, and bits below the start of the range get set: "1-1:1/4294967295" -> bits 0,1 (expected bit 1) "15-15:1/4294967281" -> bits 0,15 (expected bit 15) The loop still terminates, because start keeps decreasing until it wraps past zero again, but the resulting mask contains bits outside the requested range. This needs a group size within 'start' of UINT_MAX, so it is unlikely to be hit by accident; all bits set stay below the end of the range, so there is no out-of-bounds write. A group larger than the range simply means that the range contains a single group, so stop the walk when the next group would start beyond UINT_MAX. Fixes: 0a5ce0831d04 ("lib/bitmap.c: make bitmap_parselist() thread-safe and much faster") Assisted-by: LLM Signed-off-by: Shashank Mohan Jain <jain.sm@gmail.com> Signed-off-by: Yury Norov <ynorov@nvidia.com>
-rw-r--r--lib/bitmap-str.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/lib/bitmap-str.c b/lib/bitmap-str.c
index b58966864657..cafd6388892f 100644
--- a/lib/bitmap-str.c
+++ b/lib/bitmap-str.c
@@ -8,6 +8,7 @@
#include <linux/hex.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/overflow.h>
#include <linux/string.h>
#include "kstrtox.h"
@@ -186,10 +187,12 @@ struct region {
static void bitmap_set_region(const struct region *r, unsigned long *bitmap)
{
- unsigned int start;
+ unsigned int start = r->start;
- for (start = r->start; start <= r->end; start += r->group_len)
+ do {
bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
+ } while (!check_add_overflow(start, r->group_len, &start) &&
+ start <= r->end);
}
static int bitmap_check_region(const struct region *r)