Skip to content

Use-after-free in audio device cleanup (regression in 3.4.0) #14856

@slouken

Description

@slouken

It also broke moonlight, downgrading SDL got it to work agian

Title: Use-after-free in audio device cleanup (regression in 3.4.0)

SDL3 Version: 3.4.0
Previous Working Version: 3.2.28
OS: Arch Linux

Description:
After upgrading from SDL3 3.2.28 to 3.4.0, applications using SDL3 audio
crash with SIGSEGV during audio device disconnect/cleanup.

Backtrace shows use-after-free in DestroyLogicalAudioDevice:

  • logdev pointer is corrupted (0xe0)
  • Physical device structure shows memory corruption
  • refcount = 0, zombie field contains garbage (980954113)

This appears to be a race condition in audio device reference counting
introduced in 3.4.0.


#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=11, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007f65578989d3 in __pthread_kill_internal (threadid=<optimized out>, signo=11) at pthread_kill.c:89
#2  0x00007f655783e3a0 in __GI_raise (sig=sig@entry=11) at ../sysdeps/posix/raise.c:26
#3  0x00007f65469caed1 in SDL_EVDEV_kbd_reraise_signal (sig=11) at /usr/src/debug/sdl3/SDL3-3.4.0/src/core/linux/SDL_evdev_kbd.c:186
#4  kbd_cleanup_signal_action (signum=11, info=<optimized out>, ucontext=<optimized out>) at /usr/src/debug/sdl3/SDL3-3.4.0/src/core/linux/SDL_evdev_kbd.c:213
#5  <signal handler called>
#6  DestroyLogicalAudioDevice (logdev=0xe0) at /usr/src/debug/sdl3/SDL3-3.4.0/src/audio/SDL_audio.c:545
#7  0x00007f65468190b5 in DestroyPhysicalAudioDevice (device=0x7f65000097a0) at /usr/src/debug/sdl3/SDL3-3.4.0/src/audio/SDL_audio.c:585
#8  0x00007f6546821afe in DestroyPhysicalAudioDevice (device=<optimized out>) at /usr/src/debug/sdl3/SDL3-3.4.0/src/audio/SDL_audio.c:614
#9  0x00007f654682221c in UnrefPhysicalAudioDevice (device=0x7f65000097a0) at /usr/src/debug/sdl3/SDL3-3.4.0/src/thread/pthread/SDL_sysrwlock.c:108
#10 ReleaseAudioDevice (device=0x7f65000097a0) at /usr/src/debug/sdl3/SDL3-3.4.0/src/audio/SDL_audio.c:407
#11 ReleaseAudioDevice (device=<optimized out>) at /usr/src/debug/sdl3/SDL3-3.4.0/src/audio/SDL_audio.c:403
#12 SDL_AudioDeviceDisconnected_OnMainThread (userdata=0x7f65000097a0) at /usr/src/debug/sdl3/SDL3-3.4.0/src/audio/SDL_audio.c:799
#13 0x00007f6546853033 in SDL_RunMainThreadCallbacks () at /usr/src/debug/sdl3/SDL3-3.4.0/src/events/SDL_events.c:1391
#14 SDL_PumpEventsInternal (push_sentinel=push_sentinel@entry=true) at /usr/src/debug/sdl3/SDL3-3.4.0/src/events/SDL_events.c:1507
#15 0x00007f6546853a0e in SDL_WaitEventTimeoutNS (event=0x7ffffb22bb60, timeoutNS=1000000000) at /usr/src/debug/sdl3/SDL3-3.4.0/src/events/SDL_events.c:1694
#16 0x00007f655dc8c3e7 in SDL_WaitEventTimeout_REAL (event2=0x7ffffb22bd20, timeout=<optimized out>) at /usr/src/debug/sdl2-compat/sdl2-compat-2.32.62/src/sdl2_compat.c:3056
#17 0x000056332a1eb7ad in Session::exec (this=0x56336b3d51b0) at streaming/session.cpp:2015
#18 0x00007f65581c4994 in QObject::event (this=<optimized out>, e=<optimized out>) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qobject.cpp:1413
#19 0x00007f655816a958 in QCoreApplication::notifyInternal2 (receiver=0x56336b3d51b0, event=event@entry=0x7f65000b4070) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qcoreapplication.cpp:1109
#20 0x00007f655816ad30 in QCoreApplication::sendEvent (receiver=<optimized out>, event=0x7f65000b4070) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qcoreapplication.cpp:1549
#21 QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=0, data=0x56336a0064c0) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qcoreapplication.cpp:1904
#22 0x00007f655844ae18 in QCoreApplication::sendPostedEvents (receiver=0x0, event_type=0) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qcoreapplication.cpp:1757
#23 postEventSourceDispatch (s=0x56336a0776a0) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:246
#24 0x00007f6556d06f8d in g_main_dispatch (context=0x56336a0a2990) at ../glib/glib/gmain.c:3565
#25 0x00007f6556d08657 in g_main_context_dispatch_unlocked (context=0x56336a0a2990) at ../glib/glib/gmain.c:4425
#26 g_main_context_iterate_unlocked (context=context@entry=0x56336a0a2990, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4490
#27 0x00007f6556d08865 in g_main_context_iteration (context=0x56336a0a2990, may_block=1) at ../glib/glib/gmain.c:4556
#28 0x00007f6558448152 in QEventDispatcherGlib::processEvents (this=0x56336a0b21f0, flags=...) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:399
#29 0x00007f6558175786 in QEventLoop::processEvents (this=0x7ffffb22c210, flags=...) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qeventloop.cpp:104
#30 QEventLoop::exec (this=0x7ffffb22c210, flags=...) at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qeventloop.cpp:186
#31 0x00007f655816f3f1 in QCoreApplication::exec () at /usr/src/debug/qt6-base/qtbase/src/corelib/kernel/qcoreapplication.cpp:1452
#32 0x000056332a19977a in main (argc=<optimized out>, argv=<optimized out>) at main.cpp:937
(gdb) print *device
$3 = {
  lock = 0x7f6500000160, 
  close_cond = 0x7f650000cff0, 
  refcount = {value = 0},              ← REFCOUNT IS ZERO (use-after-free!)
  ...
  zombie = {value = 980954113},        ← GARBAGE (should be 0 or 1)
  recording = 98,                      ← GARBAGE (should be boolean)
  simple_copy = 52,                    ← GARBAGE (should be boolean)
  ...
  hidden = 0x2c31,                     ← SUSPICIOUS
  logical_devices = 0xe0               ← INVALID POINTER (crashes here)
}

Originally posted by @praxis88 in #14822

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions