]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: dict: hold read lock while incrementing refcount in dict_insert
authorWilly Tarreau <w@1wt.eu>
Wed, 13 May 2026 08:57:29 +0000 (10:57 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 13 May 2026 11:37:53 +0000 (13:37 +0200)
In dict_insert(), the read lock on d->rwlock was released before
incrementing the entry's refcount. Between the RDUNLOCK and the
HA_ATOMIC_INC, another thread could call dict_entry_unref() to drop
the refcount to zero, acquire the write lock, delete the entry from
the tree, and free it. The subsequent HA_ATOMIC_INC would then be a
use-after-free on freed memory.

The fix moves the HA_ATOMIC_INC inside the read lock, matching the
pattern used in stick_table.c for identical refcount-then-unlock
sequences.

It can be backported to the branches where this is relevant.

src/dict.c

index 61751eb1ee686f4531334e3e221ada45b4609250..c4c54664e68dc2d6db0fade5490a28bbdc635999 100644 (file)
@@ -84,11 +84,12 @@ struct dict_entry *dict_insert(struct dict *d, char *s)
 
        HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
        de = __dict_lookup(d, s);
-       HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
        if (de) {
                HA_ATOMIC_INC(&de->refcount);
+               HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
                return de;
        }
+       HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
 
        de = new_dict_entry(s);
        if (!de)