sway

i3-compatible Wayland compositor
git clone https://git.awy.one/sway
Log | Files | Refs | README | LICENSE

commit e5ece5f8b3ec14bfdbea20597ff1db82369d6331
parent 8393266eb5ab046d591595593d8966fa3c791bd5
Author: Dominique Martinet <asmadeus@codewreck.org>
Date:   Sun,  7 Oct 2018 16:33:26 +0900

swaynag: fix use-after-free in wl_display_dispatch

When destroying swaynag from within wl_display_dispatch, we cannot
disconnect the display as that will free the queue's event_list.
Free it after running the loop instead.

Fixes this use-after-free:
==7312==ERROR: AddressSanitizer: heap-use-after-free on address 0x612000000110 at pc 0x000000412a9f bp 0x7ffd4e811760 sp 0x7ffd4e811750
READ of size 8 at 0x612000000110 thread T0
    #0 0x412a9e in wl_list_empty ../common/list.c:206
    #1 0x7f5b58f0d42f in dispatch_queue src/wayland-client.c:1572
    #2 0x7f5b58f0d42f in wl_display_dispatch_queue_pending src/wayland-client.c:1815
    #3 0x40f465 in swaynag_run ../swaynag/swaynag.c:390
    #4 0x407576 in main ../swaynag/main.c:123
    #5 0x7f5b58bb9412 in __libc_start_main ../csu/libc-start.c:308
    #6 0x404a3d in _start (/opt/wayland/bin/swaynag+0x404a3d)

0x612000000110 is located 208 bytes inside of 320-byte region [0x612000000040,0x612000000180)
freed by thread T0 here:
    #0 0x7f5b594ab480 in free (/lib64/libasan.so.5+0xef480)
    #1 0x40faff in swaynag_destroy ../swaynag/swaynag.c:454
    #2 0x40cbb4 in layer_surface_closed ../swaynag/swaynag.c:82
    #3 0x7f5b583e1acd in ffi_call_unix64 (/lib64/libffi.so.6+0x6acd)

previously allocated by thread T0 here:
    #0 0x7f5b594aba50 in __interceptor_calloc (/lib64/libasan.so.5+0xefa50)
    #1 0x7f5b58f0c902 in wl_display_connect_to_fd src/wayland-private.h:236

(you need a wayland compiled with asan, my wl_list hack, or running
with valgrind to see this trace)

Diffstat:
Mswaynag/swaynag.c | 8++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c @@ -390,6 +390,10 @@ void swaynag_run(struct swaynag *swaynag) { && wl_display_dispatch(swaynag->display) != -1) { // This is intentionally left blank } + + if (swaynag->display) { + wl_display_disconnect(swaynag->display); + } } void swaynag_destroy(struct swaynag *swaynag) { @@ -449,8 +453,4 @@ void swaynag_destroy(struct swaynag *swaynag) { if (swaynag->shm) { wl_shm_destroy(swaynag->shm); } - - if (swaynag->display) { - wl_display_disconnect(swaynag->display); - } }