use after free on deinit
- PipeWire version (
pipewire --version
): 0.3.62 (3a443b4e) - Distribution and distribution version (
PRETTY_NAME
from/etc/os-release
): NixOS 23.05 (Stoat) - Desktop Environment: no
- Kernel version (
uname -r
): 6.0.9
Description of Problem:
Initially reported at mpv, see there for full context: https://github.com/mpv-player/mpv/issues/10959
When running mpv with the pipewire backend (mpv --ao=pipewire,pulse file
) on a system without pipewire running, a crash occurs when waking up from suspend.
Enabling ASan reveals a use-after-free when mpv calls pw_deinit
after deciding that pipewire isn't available. See attachments.
How Reproducible:
Steps to Reproduce:
On a Linux system using PulseAudio, not PipeWire:
- compile mpv and pipewire with
-fsanitize=address,undefined
- run
mpv --no-config --ao=pipewire,pulse file.mp4
- kaboom
Additional Info (as attachments):
asan trace
[ao/pipewire] Could not connect to context '(null)': Host is down
=================================================================
==3646909==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c0001667d0 at pc 0x7f9dfea64cbd bp 0x7ffff7138620 sp 0x7ffff7138618
READ of size 8 at 0x60c0001667d0 thread T0
#0 0x7f9dfea64cbc in remove_from_poll ../spa/plugins/support/loop.c:153
#1 0x7f9dfea6f3a3 in loop_destroy_source ../spa/plugins/support/loop.c:794
#2 0x7f9dfea700f0 in impl_clear ../spa/plugins/support/loop.c:873
#3 0x7f9e2384792d in unref_handle ../src/pipewire/pipewire.c:211
#4 0x7f9e2384bea4 in pw_deinit ../src/pipewire/pipewire.c:701
#5 0x47520d in uninit ../audio/out/ao_pipewire.c:300
#6 0x48d193 in init ../audio/out/ao_pipewire.c:564
#7 0x457118 in ao_init ../audio/out/ao.c:218
#8 0x458d18 in ao_init_best ../audio/out/ao.c:339
#9 0x6731f0 in reinit_audio_filters_and_output ../player/audio.c:441
#10 0x676da3 in fill_audio_out_buffers ../player/audio.c:884
#11 0x726ade in run_playloop ../player/playloop.c:1212
#12 0x700842 in play_current_file ../player/loadfile.c:1679
#13 0x702238 in mp_play_files ../player/loadfile.c:1865
#14 0x70e119 in mpv_main ../player/main.c:432
#15 0x4212be in main ../osdep/main-fn-unix.c:5
#16 0x7f9e2182924d in __libc_start_call_main (/nix/store/4nlgxhb09sdr51nc9hdm8az5b08vzkgx-glibc-2.35-163/lib/libc.so.6+0x2924d)
#17 0x7f9e21829308 in __libc_start_main_impl (/nix/store/4nlgxhb09sdr51nc9hdm8az5b08vzkgx-glibc-2.35-163/lib/libc.so.6+0x29308)
#18 0x4211f4 in _start (/nix/store/jd6gw9hwambj9slyk1y9i98232f7bq95-mpv-0.35.0/bin/mpv+0x4211f4)
0x60c0001667d0 is located 80 bytes inside of 128-byte region [0x60c000166780,0x60c000166800)
freed by thread T0 here:
#0 0x7f9e26cb14d7 in free (/nix/store/mdck89nsfisflwjv6xv8ydj7dj0sj2pn-gcc-11.3.0-lib/lib/libasan.so.6+0xb14d7)
#1 0x7f9e238479a7 in unref_handle ../src/pipewire/pipewire.c:215
previously allocated by thread T0 here:
#0 0x7f9e26cb1987 in __interceptor_calloc (/nix/store/mdck89nsfisflwjv6xv8ydj7dj0sj2pn-gcc-11.3.0-lib/lib/libasan.so.6+0xb1987)
#1 0x7f9e2384a14a in load_spa_handle ../src/pipewire/pipewire.c:275
SUMMARY: AddressSanitizer: heap-use-after-free ../spa/plugins/support/loop.c:153 in remove_from_poll
Shadow bytes around the buggy address:
0x0c1880024ca0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c1880024cb0: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
0x0c1880024cc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c1880024cd0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c1880024ce0: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
=>0x0c1880024cf0: fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd
0x0c1880024d00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c1880024d10: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
0x0c1880024d20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c1880024d30: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c1880024d40: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==3646909==ABORTING
mpv code that calls pw_deinit
: https://github.com/mpv-player/mpv/blob/25b66256d7ff48254b2055a066e29f260414112f/audio/out/ao_pipewire.c#L285-L303