aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBenoît Ganne <bganne@cisco.com>2024-11-20 14:54:55 +0100
committerFlorin Coras <florin.coras@gmail.com>2024-11-29 21:55:28 +0000
commit6b224de844539bde50913575305cddda09f3b2a6 (patch)
tree1c446cccaa93756dac3809fd10743088a9fa97a0 /src
parent709f40c29d5c8d8b8974823aae537d52a91afa30 (diff)
svm: fix overflow when no region is big enough
- if no region is big enough to accommodate need_n_bits, we can scan past the end of the bitmask - rewrite the search loop for clarity Type: fix Change-Id: I82637bc91eb7e7ae922785bc626fa224638cb4e4 Signed-off-by: Benoît Ganne <bganne@cisco.com>
Diffstat (limited to 'src')
-rw-r--r--src/svm/svm.c52
1 files changed, 20 insertions, 32 deletions
diff --git a/src/svm/svm.c b/src/svm/svm.c
index d32c0a5d4db..92f6469b7dc 100644
--- a/src/svm/svm.c
+++ b/src/svm/svm.c
@@ -892,7 +892,7 @@ svm_region_find_or_create (svm_map_region_args_t * a)
svm_main_region_t *mp;
svm_region_t *rp;
uword need_nbits;
- int index, i;
+ int index;
void *oldheap;
uword *p;
u8 *name;
@@ -933,39 +933,31 @@ svm_region_find_or_create (svm_map_region_args_t * a)
need_nbits = a->size / MMAP_PAGESIZE;
- index = 1; /* $$$ fixme, figure out how many bit to really skip */
-
/*
* Scan the virtual space allocation bitmap, looking for a large
* enough chunk
*/
- do
+ index = 0;
+ for (;;)
{
- if (clib_bitmap_get_no_check (root_rp->bitmap, index) == 0)
+ index = clib_bitmap_next_clear (root_rp->bitmap, index);
+ uword n = clib_bitmap_next_set (root_rp->bitmap, index + 1);
+ /* if we reach the end of the bitmap, clib_bitmap_next_set() returns ~0
+ * in that case, check the remaining is enough */
+ if (~0 == n &&
+ vec_len (root_rp->bitmap) * BITS (root_rp->bitmap[0]) - index <
+ need_nbits)
{
- for (i = 0; i < (need_nbits - 1); i++)
- {
- if (clib_bitmap_get_no_check (root_rp->bitmap, index + i) == 1)
- {
- index = index + i;
- goto next;
- }
- }
- break;
+ clib_warning ("region %s: not enough VM to allocate 0x%llx (%lld)",
+ root_rp->region_name, a->size, a->size);
+ svm_pop_heap (oldheap);
+ region_unlock (root_rp);
+ return 0;
}
- index++;
- next:;
- }
- while (index < root_rp->bitmap_size);
-
- /* Completely out of VM? */
- if (index >= root_rp->bitmap_size)
- {
- clib_warning ("region %s: not enough VM to allocate 0x%llx (%lld)",
- root_rp->region_name, a->size, a->size);
- svm_pop_heap (oldheap);
- region_unlock (root_rp);
- return 0;
+ if (n - index >= need_nbits)
+ break; /* found */
+ /* continue looking for next */
+ index = n + 1;
}
/*
@@ -974,11 +966,7 @@ svm_region_find_or_create (svm_map_region_args_t * a)
#if CLIB_DEBUG > 1
clib_warning ("set %d bits at index %d", need_nbits, index);
#endif
-
- for (i = 0; i < need_nbits; i++)
- {
- clib_bitmap_set_no_check (root_rp->bitmap, index + i, 1);
- }
+ clib_bitmap_set_region (root_rp->bitmap, index, 1, need_nbits);
/* Place this region where it goes... */
a->baseva = root_rp->virtual_base + index * MMAP_PAGESIZE;