From a5e32f652b84ae71e207af6b9615a69c7738928f Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Thu, 30 May 2019 08:09:11 +0200 Subject: [PATCH] wlr_output: remove idle_done on output destroy If an output is destroyed while an idle_done event is scheduled, it results in the following Address Sanitizer Output: ==1469==ERROR: AddressSanitizer: heap-use-after-free on address 0x6170000bb668 at pc 0x7f49aaa0c348 bp 0x7ffed5da35b0 sp 0x7ffed5da35a0 WRITE of size 8 at 0x6170000bb668 thread T0 #0 0x7f49aaa0c347 in schedule_done_handle_idle_timer ../subprojects/wlroots/types/wlr_output.c:265 #1 0x7f49aa2f875b in wl_event_loop_dispatch_idle (/usr/lib/libwayland-server.so.0+0xa75b) #2 0x7f49aa2f8815 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa815) #3 0x7f49aa2f739b in wl_display_run (/usr/lib/libwayland-server.so.0+0x939b) #4 0x556622dadd51 in server_run ../sway/server.c:216 #5 0x556622dac25d in main ../sway/main.c:397 #6 0x7f49aa0d0ce2 in __libc_start_main (/usr/lib/libc.so.6+0x23ce2) #7 0x556622d8d09d in _start (/usr/local/bin/sway+0x3909d) 0x6170000bb668 is located 488 bytes inside of 672-byte region [0x6170000bb480,0x6170000bb720) freed by thread T0 here: #0 0x7f49aabc8f89 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:66 #1 0x7f49aa968fc2 in drm_connector_destroy ../subprojects/wlroots/backend/drm/drm.c:829 #2 0x7f49aaa0cc52 in wlr_output_destroy ../subprojects/wlroots/types/wlr_output.c:357 #3 0x7f49aa96d2e9 in scan_drm_connectors ../subprojects/wlroots/backend/drm/drm.c:1265 #4 0x7f49aa961a59 in drm_invalidated ../subprojects/wlroots/backend/drm/backend.c:135 #5 0x7f49aaa2e1e9 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 #6 0x7f49aa98319f in udev_event ../subprojects/wlroots/backend/session/session.c:52 #7 0x7f49aa2f87f1 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa7f1) previously allocated by thread T0 here: #0 0x7f49aabc95a1 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:95 #1 0x7f49aa96b7a2 in scan_drm_connectors ../subprojects/wlroots/backend/drm/drm.c:1114 #2 0x7f49aa961a59 in drm_invalidated ../subprojects/wlroots/backend/drm/backend.c:135 #3 0x7f49aaa2e1e9 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 #4 0x7f49aa98319f in udev_event ../subprojects/wlroots/backend/session/session.c:52 #5 0x7f49aa2f87f1 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa7f1) SUMMARY: AddressSanitizer: heap-use-after-free ../subprojects/wlroots/types/wlr_output.c:265 in schedule_done_handle_idle_timer Shadow bytes around the buggy address: 0x0c2e8000f670: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2e8000f680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2e8000f690: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2e8000f6a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2e8000f6b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd =>0x0c2e8000f6c0: fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd 0x0c2e8000f6d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2e8000f6e0: fd fd fd fd fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2e8000f6f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2e8000f700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2e8000f710: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Remove the idle_done idle timer when the output is destroyed --- types/wlr_output.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/types/wlr_output.c b/types/wlr_output.c index 27f5c3ff92..f04811a303 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -350,6 +350,10 @@ void wlr_output_destroy(struct wlr_output *output) { wl_event_source_remove(output->idle_frame); } + if (output->idle_done != NULL) { + wl_event_source_remove(output->idle_done); + } + pixman_region32_fini(&output->pending.damage); pixman_region32_fini(&output->damage);