#1842·libevent

UAF via shared lock lifetime mismatch in `bufferevent_finalize_cb_`

Author: BrubbishCreated Mar 17, 2026Updated May 25, 2026

Summary

When evbuffer_add_buffer_reference() makes an evbuffer’s refcount > 1, calling bufferevent_free() can free a shared lock while the evbuffer remains alive. Any subsequent lock operation on that evbuffer can dereference a freed lock pointer, causing a use‑after‑free.

Affected Version

  • libevent built from source (commit id: a994a52d5373d6284b27576efa617aff2baa7bd3)
  • Components: bufferevent.c, buffer.c

Reproduction Environment

  • Debian trixie container
  • AddressSanitizer (ASAN)

Vulnerability Details

Location

  • bufferevent_finalize_cb_ in bufferevent.c
  • evbuffer_decref_and_unlock_ in buffer.c
  • evbuffer_add_buffer_reference in buffer.c

Root Cause (code pattern)

// bufferevent_finalize_cb_()
/* evbuffer will free the callbacks */
evbuffer_free(bufev->input);
evbuffer_free(bufev->output);
...
if (bufev_private->own_lock)
    EVTHREAD_FREE_LOCK(bufev_private->lock, EVTHREAD_LOCKTYPE_RECURSIVE);

If evbuffer_add_buffer_reference() has incremented the evbuffer refcount, evbuffer_free() only decrements the refcount and does not destroy the buffer. However, bufferevent_finalize_cb_() still frees the shared lock. The surviving evbuffer then uses a dangling lock pointer.

PoC / Steps to Reproduce

1) PoC Source

poc_uaf_lock.c

2) Build & Run (container)

bash
docker run --rm -v /home/bruce/libevent:/src debian-trixie-tsinghua:latest bash -lc "
set -e
apt-get update >/dev/null
apt-get install -y build-essential cmake autoconf automake libtool pkg-config >/dev/null

rm -rf /src/build && mkdir -p /src/build && cd /src/build
cmake -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_BENCHMARK=ON .. >/dev/null
cmake --build . -j2 >/dev/null

cd /src/poc
gcc -g -fsanitize=address -I/src -I/src/include -I/src/build/include -L/src/build/lib \
    poc_uaf_lock.c -o poc_uaf_lock -levent -levent_core -levent_extra -levent_pthreads -pthread

ASAN_OPTIONS=detect_odr_violation=0 LD_LIBRARY_PATH=/src/build/lib ./poc_uaf_lock
"

3) Expected ASAN Result

==1==ERROR: AddressSanitizer: heap-use-after-free on address 0x50d000000078 at pc 0x5614b35499e4 bp 0x7ffc9e7bf6c0 sp 0x7ffc9e7bf6b8
READ of size 8 at 0x50d000000078 thread T0
    #0 0x5614b35499e3 in main /src/poc/poc_uaf_lock.c:89
    #1 0x7f7b0310dca7  (/lib/x86_64-linux-gnu/libc.so.6+0x29ca7) (BuildId: 58749c528985eab03e6700ebc1469fa50aa41219)
    #2 0x7f7b0310dd64 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29d64) (BuildId: 58749c528985eab03e6700ebc1469fa50aa41219)
    #3 0x5614b3549270 in _start (/src/poc/poc_uaf_lock+0x2270) (BuildId: 6395d19b949aa674aaebe690eed280c5504f30cc)

0x50d000000078 is located 56 bytes inside of 144-byte region [0x50d000000040,0x50d0000000d0)
freed by thread T0 here:
    #0 0x7f7b034c08f8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x7f7b0337d347 in bufferevent_finalize_cb_ (/src/build/lib/libevent-2.2.so.1+0x1d347) (BuildId: 86dd64a7209032eeb6e3047fe7ac180d2569754f)

previously allocated by thread T0 here:
    #0 0x7f7b034c1610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f7b03371d72 in evbuffer_new (/src/build/lib/libevent-2.2.so.1+0x11d72) (BuildId: 86dd64a7209032eeb6e3047fe7ac180d2569754f)

SUMMARY: AddressSanitizer: heap-use-after-free /src/poc/poc_uaf_lock.c:89 in main

Impact

Use‑after‑free of a mutex/lock associated with an evbuffer can lead to crashes and potentially security issues in threaded environments.