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:

committed by
Florin Coras

parent
709f40c29d
commit
6b224de844
@ -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;
|
||||||
|
Reference in New Issue
Block a user