DEBUG: pool: permit per-pool UAF configuration

The new MEM_F_UAF flag can be set just after a pool's creation to make
this pool UAF for debugging purposes. This allows to maintain a better
overall performance required to reproduce issues while still having a
chance to catch UAF. It will only be used by developers who will manually
add it to areas worth being inspected, though.
This commit is contained in:
Willy Tarreau 2025-05-08 19:52:16 +02:00
parent 14e4f2b811
commit 0ae14beb2a
3 changed files with 7 additions and 3 deletions

View File

@ -342,7 +342,9 @@ struct pool_head *create_pool(char *name, uint size, uint flags)
"-dMno-merge" is passed on the executable's command line, the pools
also need to have the exact same name to be merged. In addition, unless
MEM_F_EXACT is set in <flags>, the object size will usually be rounded
up to the size of pointers (16 or 32 bytes). The name that will appear
up to the size of pointers (16 or 32 bytes). MEM_F_UAF may be set on a
per-pool basis to enable the UAF detection only for this specific pool,
saving the massive overhead of global usage. The name that will appear
in the pool upon merging is the name of the first created pool. The
returned pointer is the new (or reused) pool head, or NULL upon error.
Pools created this way must be destroyed using pool_destroy().

View File

@ -27,6 +27,7 @@
#define MEM_F_SHARED 0x1
#define MEM_F_EXACT 0x2
#define MEM_F_UAF 0x4
/* A special pointer for the pool's free_list that indicates someone is
* currently manipulating it. Serves as a short-lived lock.

View File

@ -440,7 +440,7 @@ void *pool_get_from_os_noinc(struct pool_head *pool)
if (!pool->limit || pool_allocated(pool) < pool->limit) {
void *ptr;
if (pool_debugging & POOL_DBG_UAF)
if ((pool_debugging & POOL_DBG_UAF) || (pool->flags & MEM_F_UAF))
ptr = pool_alloc_area_uaf(pool->alloc_sz);
else
ptr = pool_alloc_area(pool->alloc_sz);
@ -459,7 +459,7 @@ void *pool_get_from_os_noinc(struct pool_head *pool)
*/
void pool_put_to_os_nodec(struct pool_head *pool, void *ptr)
{
if (pool_debugging & POOL_DBG_UAF)
if ((pool_debugging & POOL_DBG_UAF) || (pool->flags & MEM_F_UAF))
pool_free_area_uaf(ptr, pool->alloc_sz);
else
pool_free_area(ptr, pool->alloc_sz);
@ -965,6 +965,7 @@ void __pool_free(struct pool_head *pool, void *ptr)
#endif
if (unlikely((pool_debugging & POOL_DBG_NO_CACHE) ||
(pool->flags & MEM_F_UAF) ||
global.tune.pool_cache_size < pool->size)) {
pool_free_nocache(pool, ptr);
return;