Skip to content

tinywl: fix wlr_seat use-after-free on exit

Simon Ser requested to merge emersion/wlroots:tinywl-backend-destroy into master

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

Merge request reports