array: Avoid issue when re-inserting existing element in value-based arrays

The insertion can cause the existing data to get reallocated/moved.  So
if the caller attempts to insert another copy of an existing element into
the array via its pointer, this can cause a undefined behavior or even
a use-after-free because the pointer might get invalid.

There is such a case in `mem_pool_t::get_existing()` since the referenced
commit.

Fixes: d4a0dd9f93 ("mem-pool: Fix issue with make-before-break reauth and multiple IKE_SAs")
This commit is contained in:
Tobias Brunner
2026-07-24 08:47:37 +02:00
parent 8b1f8e0e46
commit 588c7a80d1
2 changed files with 23 additions and 3 deletions
+21 -2
View File
@@ -310,11 +310,30 @@ void array_insert_enumerator(array_t *array, int idx, enumerator_t *enumerator)
enumerator->destroy(enumerator);
}
/**
* Check if the given pointer points to an array element
*/
static bool is_in_array(array_t *array, void *ptr)
{
return array->data && ptr >= array->data &&
ptr < array->data + get_size(array, array->head + array->count +
array->tail);
}
void array_insert(array_t *array, int idx, void *data)
{
if (idx < 0 || idx <= array_count(array))
{
void *pos;
void *buf, *pos, *src = data;
/* create a local copy if the source is another element in the array.
* due to the resizing/moving, it might get invalid */
if (array->esize && is_in_array(array, data))
{
buf = alloca(array->esize);
memcpy(buf, data, array->esize);
src = buf;
}
if (idx < 0)
{
@@ -341,7 +360,7 @@ void array_insert(array_t *array, int idx, void *data)
pos = array->data + get_size(array, array->head + idx);
if (array->esize)
{
memcpy(pos, data, get_size(array, 1));
memcpy(pos, src, array->esize);
}
else
{
+2 -1
View File
@@ -113,7 +113,8 @@ void array_remove_at(array_t *array, enumerator_t *enumerator);
* Insert an element to an array.
*
* If the array is pointer based (esize = 0), the pointer itself is appended.
* Otherwise the element gets copied from the pointer.
* Otherwise, the element gets copied from the pointer.
*
* The idx must be either within array_count() or one above to append the item.
* Passing -1 has the same effect as passing array_count(), i.e. appends the
* item. It is always valid to pass idx 0 to prepend the item.