tinywl: fix wlr_seat use-after-free on exit

When pressing the keybinding to shut down the compositor, the following
use-after-free is triggered:

    ==1165966==ERROR: AddressSanitizer: heap-use-after-free on address 0x51800000ade0 at pc 0x7fa6728b4531 bp 0x7ffe540a6aa0 sp 0x7ffe540a6a90
    READ of size 8 at 0x51800000ade0 thread T0
        #0 0x7fa6728b4530 in wlr_seat_set_keyboard ../types/seat/wlr_seat_keyboard.c:124
        #1 0x58a83fa7fd4e in keyboard_handle_key ../tinywl/tinywl.c:228
        #2 0x7fa673a1901d in wl_signal_emit_mutable (/usr/lib/libwayland-server.so.0+0xa01d) (BuildId: d943a6a6069d1b5293dad7c842d26ce407ebdd19)
        #3 0x7fa67295b4be in wlr_keyboard_notify_key ../types/wlr_keyboard.c:102
        #4 0x7fa67295c791 in wlr_keyboard_finish ../types/wlr_keyboard.c:165
        #5 0x7fa672848cb1 in destroy_wl_seat ../backend/wayland/seat.c:293
        #6 0x7fa672833dca in backend_destroy ../backend/wayland/backend.c:493
        #7 0x7fa6727b49e8 in wlr_backend_destroy ../backend/backend.c:67
        #8 0x7fa67282d334 in multi_backend_destroy ../backend/multi/backend.c:59
        #9 0x7fa67282da5a in handle_event_loop_destroy ../backend/multi/backend.c:110
        #10 0x7fa673a18b98 in wl_event_loop_destroy (/usr/lib/libwayland-server.so.0+0x9b98) (BuildId: d943a6a6069d1b5293dad7c842d26ce407ebdd19)
        #11 0x7fa673a1b43c in wl_display_destroy (/usr/lib/libwayland-server.so.0+0xc43c) (BuildId: d943a6a6069d1b5293dad7c842d26ce407ebdd19)
        #12 0x58a83fa8ada1 in main ../tinywl/tinywl.c:1068
        #13 0x7fa672043ccf  (/usr/lib/libc.so.6+0x25ccf) (BuildId: c0caa0b7709d3369ee575fcd7d7d0b0fc48733af)
        #14 0x7fa672043d89 in __libc_start_main (/usr/lib/libc.so.6+0x25d89) (BuildId: c0caa0b7709d3369ee575fcd7d7d0b0fc48733af)
        #15 0x58a83fa7e7c4 in _start (/home/simon/src/wlroots/build/tinywl/tinywl+0x167c4) (BuildId: 1febf2a5a18bda0f6b67377a132484061875e248)

    0x51800000ade0 is located 352 bytes inside of 880-byte region [0x51800000ac80,0x51800000aff0)
    freed by thread T0 here:
        #0 0x7fa6732dfdb2 in __interceptor_free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
        #1 0x7fa6728c6a1e in wlr_seat_destroy ../types/seat/wlr_seat.c:245
        #2 0x7fa6728c6a7a in handle_display_destroy ../types/seat/wlr_seat.c:251
        #3 0x7fa673a1b3c6 in wl_display_destroy (/usr/lib/libwayland-server.so.0+0xc3c6) (BuildId: d943a6a6069d1b5293dad7c842d26ce407ebdd19)

    previously allocated by thread T0 here:
        #0 0x7fa6732e0cc1 in __interceptor_calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
        #1 0x7fa6728c6a9d in wlr_seat_create ../types/seat/wlr_seat.c:255
        #2 0x58a83fa8a8d3 in main ../tinywl/tinywl.c:1024
        #3 0x7fa672043ccf  (/usr/lib/libc.so.6+0x25ccf) (BuildId: c0caa0b7709d3369ee575fcd7d7d0b0fc48733af)

This happens because the wlr_seat is destroyed before the
wlr_keyboard. Destroying the wlr_keyboard has the side effect of
implicitly releasing keys currently held down.

Explicitly destroying the wlr_backend before the wl_display fixes
this.

Suggested-by: Isaac Freund <ifreund@ifreund.xyz>
This commit is contained in:
Simon Ser 2024-03-04 13:34:50 +01:00 committed by Isaac Freund
parent 16b42bf65b
commit 7915a2ff59

View file

@ -1065,6 +1065,7 @@ int main(int argc, char *argv[]) {
wl_display_destroy_clients(server.wl_display);
wlr_scene_node_destroy(&server.scene->tree.node);
wlr_xcursor_manager_destroy(server.cursor_mgr);
wlr_backend_destroy(server.backend);
wl_display_destroy(server.wl_display);
return 0;
}