]> git.ipfire.org Git - thirdparty/haproxy.git/commit
BUG/MINOR: dict: fix refcount race on insert collision
authorWilly Tarreau <w@1wt.eu>
Sat, 23 May 2026 20:17:10 +0000 (22:17 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 25 May 2026 08:52:42 +0000 (10:52 +0200)
commitc0e302fe79a127e7093a14757351e85cfba20b24
treea037c92331a74b4fae56e80507f653dd2b60095b
parent478e7e52cb220075a6c1eb796ca18391189a29ab
BUG/MINOR: dict: fix refcount race on insert collision

In dict_insert(), when ebis_insert() returns an existing node n indicating
that another thread inserted the same key concurrently, the code freed its
own newly-allocated entry and returned the winner without bumping its
refcount. Both callers then held a reference with refcount=1 instead of 2,
so when one expires the other becomes a use-after-free or double-free.

The bug likely comes from the fact that new_dict_entry() creates an entry
with a refcount preset to 1 (saves an atomic op) and that because of this
there is no refcount increment upon a successful insertion in the tree,
resulting in requiring different code paths for collision and normal
insertion.

A simple fix consists in bumping the refcount under the lock and unlocking
only at the end, but this would mean performing two free() calls under a
lock, which we always try to avoid. The code was slightly rearranged so
that we can now bump the existing entry's refcount under the lock in case
of duplicate, or unlock immediately in the common case, so that the free()
call is done out of the lock.

The probably of the race is very low (at peers connection setup only),
reason why it's marked low. This should be backported to all versions.
src/dict.c