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>
This commit is contained in:
Benoît Ganne
2024-11-20 14:54:55 +01:00
committed by Florin Coras
parent 709f40c29d
commit 6b224de844

View File

@ -892,7 +892,7 @@ svm_region_find_or_create (svm_map_region_args_t * a)
svm_main_region_t *mp; svm_main_region_t *mp;
svm_region_t *rp; svm_region_t *rp;
uword need_nbits; uword need_nbits;
int index, i; int index;
void *oldheap; void *oldheap;
uword *p; uword *p;
u8 *name; u8 *name;
@ -933,39 +933,31 @@ svm_region_find_or_create (svm_map_region_args_t * a)
need_nbits = a->size / MMAP_PAGESIZE; 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 * Scan the virtual space allocation bitmap, looking for a large
* enough chunk * 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++) clib_warning ("region %s: not enough VM to allocate 0x%llx (%lld)",
{ root_rp->region_name, a->size, a->size);
if (clib_bitmap_get_no_check (root_rp->bitmap, index + i) == 1) svm_pop_heap (oldheap);
{ region_unlock (root_rp);
index = index + i; return 0;
goto next;
}
}
break;
} }
index++; if (n - index >= need_nbits)
next:; break; /* found */
} /* continue looking for next */
while (index < root_rp->bitmap_size); index = n + 1;
/* 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;
} }
/* /*
@ -974,11 +966,7 @@ svm_region_find_or_create (svm_map_region_args_t * a)
#if CLIB_DEBUG > 1 #if CLIB_DEBUG > 1
clib_warning ("set %d bits at index %d", need_nbits, index); clib_warning ("set %d bits at index %d", need_nbits, index);
#endif #endif
clib_bitmap_set_region (root_rp->bitmap, index, 1, need_nbits);
for (i = 0; i < need_nbits; i++)
{
clib_bitmap_set_no_check (root_rp->bitmap, index + i, 1);
}
/* Place this region where it goes... */ /* Place this region where it goes... */
a->baseva = root_rp->virtual_base + index * MMAP_PAGESIZE; a->baseva = root_rp->virtual_base + index * MMAP_PAGESIZE;