]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: pools: move pool_free_area() out of the lock in the locked version
authorWilly Tarreau <w@1wt.eu>
Sat, 17 Apr 2021 16:19:51 +0000 (18:19 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 19 Apr 2021 13:24:33 +0000 (15:24 +0200)
Calling pool_free_area() inside a lock in pool_put_to_shared_cache() is
a very bad idea. Fortunately this only happens on the lowest end platforms
which almost never use threads or in very small counts.

This change consists in zeroing the pointer once already released to the
cache in the first test so that the second stage knows if it needs to
pass it to the OS or not. This has slightly reduced the length of the

include/haproxy/pool.h

index a44062556f3b5a2eec908f0775addfbacc7c766f..8fce5932d7cff6fcd9cab6118fface99549f3206 100644 (file)
@@ -237,26 +237,31 @@ static inline void *pool_get_from_shared_cache(struct pool_head *pool)
  */
 static inline void pool_put_to_shared_cache(struct pool_head *pool, void *ptr)
 {
-#ifndef DEBUG_UAF /* normal pool behaviour */
        _HA_ATOMIC_DEC(&pool->used);
+
+#ifndef DEBUG_UAF /* normal pool behaviour */
+
        HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
-       if (pool_is_crowded(pool)) {
-               pool_free_area(ptr, pool->size + POOL_EXTRA);
-               _HA_ATOMIC_DEC(&pool->allocated);
-       } else {
+       if (!pool_is_crowded(pool)) {
                *POOL_LINK(pool, ptr) = (void *)pool->free_list;
                pool->free_list = (void *)ptr;
+               ptr = NULL;
        }
-       swrate_add(&pool->needed_avg, POOL_AVG_SAMPLES, pool->used);
        HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
-#else  /* release the entry for real to detect use after free */
-       /* ensure we crash on double free or free of a const area*/
+
+#else
+       /* release the entry for real to detect use after free */
+       /* ensure we crash on double free or free of a const area */
        *(uint32_t *)ptr = 0xDEADADD4;
-       pool_free_area(ptr, pool->size + POOL_EXTRA);
-       _HA_ATOMIC_DEC(&pool->allocated);
-       _HA_ATOMIC_DEC(&pool->used);
-       swrate_add(&pool->needed_avg, POOL_AVG_SAMPLES, pool->used);
+
 #endif /* DEBUG_UAF */
+
+       if (ptr) {
+               /* still not freed */
+               pool_free_area(ptr, pool->size + POOL_EXTRA);
+               _HA_ATOMIC_DEC(&pool->allocated);
+       }
+       swrate_add(&pool->needed_avg, POOL_AVG_SAMPLES, pool->used);
 }
 
 #endif /* CONFIG_HAP_LOCKLESS_POOLS */