This fixes a heap-use-after-free when the session is destroyed before
the backend during wl_display_destroy:
==1085==ERROR: AddressSanitizer: heap-use-after-free on address 0x614000000180 at pc 0x7f88e3590c2d bp 0x7ffdc4e33f90 sp 0x7ffdc4e33f80
READ of size 8 at 0x614000000180 thread T0
#0 0x7f88e3590c2c in find_device ../subprojects/wlroots/backend/session/session.c:192
#1 0x7f88e3590e85 in wlr_session_close_file ../subprojects/wlroots/backend/session/session.c:204
#2 0x7f88e357b80c in libinput_close_restricted ../subprojects/wlroots/backend/libinput/backend.c:24
#3 0x7f88e21af274 (/lib64/libinput.so.10+0x28274)
#4 0x7f88e21aff1d (/lib64/libinput.so.10+0x28f1d)
#5 0x7f88e219ddac (/lib64/libinput.so.10+0x16dac)
#6 0x7f88e21b415d in libinput_unref (/lib64/libinput.so.10+0x2d15d)
#7 0x7f88e357c9d6 in backend_destroy ../subprojects/wlroots/backend/libinput/backend.c:130
#8 0x7f88e3545a09 in wlr_backend_destroy ../subprojects/wlroots/backend/backend.c:50
#9 0x7f88e358981a in multi_backend_destroy ../subprojects/wlroots/backend/multi/backend.c:54
#10 0x7f88e358a059 in handle_display_destroy ../subprojects/wlroots/backend/multi/backend.c:107
#11 0x7f88e314acde (/lib64/libwayland-server.so.0+0x8cde)
#12 0x7f88e314b466 in wl_display_destroy (/lib64/libwayland-server.so.0+0x9466)
#13 0x559fefb52385 in main ../main.c:67
#14 0x7f88e2639152 in __libc_start_main (/lib64/libc.so.6+0x27152)
#15 0x559fefb4297d in _start (/home/simon/src/glider/build/glider+0x2297d)
0x614000000180 is located 320 bytes inside of 416-byte region [0x614000000040,0x6140000001e0)
freed by thread T0 here:
#0 0x7f88e3d0a6b0 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
#1 0x7f88e35b51fb in logind_session_destroy ../subprojects/wlroots/backend/session/logind.c:270
#2 0x7f88e35905a4 in wlr_session_destroy ../subprojects/wlroots/backend/session/session.c:156
#3 0x7f88e358f440 in handle_display_destroy ../subprojects/wlroots/backend/session/session.c:65
#4 0x7f88e314acde (/lib64/libwayland-server.so.0+0x8cde)
previously allocated by thread T0 here:
#0 0x7f88e3d0acd8 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:153
#1 0x7f88e35b911c in logind_session_create ../subprojects/wlroots/backend/session/logind.c:746
#2 0x7f88e358f6b4 in wlr_session_create ../subprojects/wlroots/backend/session/session.c:91
#3 0x559fefb51ea6 in main ../main.c:20
#4 0x7f88e2639152 in __libc_start_main (/lib64/libc.so.6+0x27152)
The backend destroy signal is emitted before the output_remove
signal is. When the destroy signal is emitted listeners remove
their output_remove listener, so the output_remove signal is never
received and listeners have an invalid output pointer.
The correct way to solve this would be to remove the output_remove
signal completely and use the wlr_output.events.destroy signal
instead. This isn't yet possible because wl_signal_emit is unsafe
and listeners cannot be removed in listeners.
This runs through events pending at init on initialization so we can
tell if some devices are available.
Note that with the way wlr_device_lists is managed, this checks that
there is at least one device we handle - it doesn't have to be a
keyboard, but there is at least a mouse or tablet_pad or something
that we care about.
Instead of failing inconditionally it might be better to leave the
decision to the user, e.g. add a "backend_has_devices" function to
call later.
(Tested by moving /dev/input off)
Fixes#24.
- 'libinput' (backend's) to libinput_context
- 'device' (libinput_device) to libinput_dev
- 'dev' (wlr_device) to wlr_dev
- 'devices' lists tangling of libinput devices to wlr_devices
- 'devices' list of wlr_devices in backend state to wlr_device_lists