From b2050be650589220d32d7e34938b5eee58a15ab6 Mon Sep 17 00:00:00 2001 From: Martin Pelikan Date: Sat, 25 Sep 2021 18:03:06 +0200 Subject: [PATCH] unlink wlr_device from wlr_session before calling libseat What happens (during Ctrl+Alt+F changing consoles away from Wayfire for example) is that callbacks within libseat_close_device will attempt to free(3) this memory twice, resulting in a crash. Proof: WARNING: ThreadSanitizer: heap-use-after-free (pid=24511) Read of size 4 at 0x7b100002c180 by main thread: #0 wlr_session_close_file ../wlroots-9999/backend/session/session.c:328 (libwlroots.so.10+0x5a8f1) #1 libinput_close_restricted ../wlroots-9999/backend/libinput/backend.c:39 (libwlroots.so.10+0x454dd) #2 close_restricted ../libinput-1.19.0/src/libinput.c:2054 (libinput.so.10+0x120ac) #3 evdev_device_suspend ../libinput-1.19.0/src/evdev.c:2873 (libinput.so.10+0x1efb1) #4 evdev_device_remove ../libinput-1.19.0/src/evdev.c:2963 (libinput.so.10+0x1f3f1) #5 evdev_device_dispatch ../libinput-1.19.0/src/evdev.c:1146 (libinput.so.10+0x1fb88) #6 libinput_dispatch ../libinput-1.19.0/src/libinput.c:2209 (libinput.so.10+0x128aa) #7 handle_libinput_readable ../wlroots-9999/backend/libinput/backend.c:50 (libwlroots.so.10+0x455e5) #8 wl_event_loop_dispatch (libwayland-server.so.0+0xa961) #9 __libc_start_main (libc.so.6+0x237fc) Previous write of size 8 at 0x7b100002c180 by main thread: #0 free /var/tmp/portage/sys-devel/gcc-11.2.0/work/gcc-11.2.0/libsanitizer/tsan/tsan_interceptors_posix.cpp:711 (libtsan.so.0+0x39ed8) #1 wlr_session_close_file ../wlroots-9999/backend/session/session.c:330 (libwlroots.so.10+0x5a90a) #2 libinput_close_restricted ../wlroots-9999/backend/libinput/backend.c:39 (libwlroots.so.10+0x454dd) #3 close_restricted ../libinput-1.19.0/src/libinput.c:2054 (libinput.so.10+0x120ac) #4 evdev_device_suspend ../libinput-1.19.0/src/evdev.c:2873 (libinput.so.10+0x1efb1) #5 evdev_device_remove ../libinput-1.19.0/src/evdev.c:2963 (libinput.so.10+0x1f3f1) #6 udev_input_remove_devices ../libinput-1.19.0/src/udev-seat.c:253 (libinput.so.10+0x506fa) #7 udev_input_disable ../libinput-1.19.0/src/udev-seat.c:272 (libinput.so.10+0x506fa) #8 libinput_suspend ../libinput-1.19.0/src/libinput.c:3232 (libinput.so.10+0x13a04) #9 session_signal ../wlroots-9999/backend/libinput/backend.c:188 (libwlroots.so.10+0x455b4) #10 wlr_signal_emit_safe ../wlroots-9999/util/signal.c:29 (libwlroots.so.10+0xa8c31) #11 handle_disable_seat ../wlroots-9999/backend/session/session.c:35 (libwlroots.so.10+0x59e96) #12 execute_events ../seatd-0.6.2/libseat/backend/seatd.c:228 (libseat.so.1+0x355f) #13 close_device ../seatd-0.6.2/libseat/backend/seatd.c:519 (libseat.so.1+0x4b9a) #14 libseat_close_device ../seatd-0.6.2/libseat/libseat.c:106 (libseat.so.1+0x26cb) #15 wlr_session_close_file ../wlroots-9999/backend/session/session.c:325 (libwlroots.so.10+0x5a8e4) #16 libinput_close_restricted ../wlroots-9999/backend/libinput/backend.c:39 (libwlroots.so.10+0x454dd) #17 close_restricted ../libinput-1.19.0/src/libinput.c:2054 (libinput.so.10+0x120ac) #18 evdev_device_suspend ../libinput-1.19.0/src/evdev.c:2873 (libinput.so.10+0x1efb1) #19 evdev_device_remove ../libinput-1.19.0/src/evdev.c:2963 (libinput.so.10+0x1f3f1) #20 evdev_device_dispatch ../libinput-1.19.0/src/evdev.c:1146 (libinput.so.10+0x1fb88) #21 libinput_dispatch ../libinput-1.19.0/src/libinput.c:2209 (libinput.so.10+0x128aa) #22 handle_libinput_readable ../wlroots-9999/backend/libinput/backend.c:50 (libwlroots.so.10+0x455e5) #23 wl_event_loop_dispatch (libwayland-server.so.0+0xa961) #24 __libc_start_main (libc.so.6+0x237fc) SUMMARY: ThreadSanitizer: heap-use-after-free ../wlroots-9999/backend/session/session.c:328 in wlr_session_close_file ================== Thread 1 "wayfire" received signal SIGSEGV, Segmentation fault. 0x00007ffff741f397 in wl_list_remove () from /usr/lib64/libwayland-server.so.0 --- backend/session/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/session/session.c b/backend/session/session.c index b98f503deb..584789f14b 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -322,11 +322,11 @@ struct wlr_device *wlr_session_open_file(struct wlr_session *session, void wlr_session_close_file(struct wlr_session *session, struct wlr_device *dev) { + wl_list_remove(&dev->link); if (libseat_close_device(session->seat_handle, dev->device_id) == -1) { wlr_log_errno(WLR_ERROR, "Failed to close device %d", dev->device_id); } close(dev->fd); - wl_list_remove(&dev->link); free(dev); }