From 3ead287064e8176520e7f15bf84fb179cbf1f1b1 Mon Sep 17 00:00:00 2001
From: Rouven Czerwinski <rouven@czerwinskis.de>
Date: Sat, 23 Feb 2019 08:28:49 +0100
Subject: [PATCH] view: set xdg_decoration->view to NULL, check decoration
 destroy

Fixes heap-use-after-free:

==32046==ERROR: AddressSanitizer: heap-use-after-free on address 0x615000064d20 at pc 0x55571ce4d303 bp 0x7fff545c64c0 sp 0x7fff545c64b0
WRITE of size 8 at 0x615000064d20 thread T0
    #0 0x55571ce4d302 in xdg_decoration_handle_destroy ../sway/xdg_decoration.c:13
    #1 0x7f64009d6f36 in wlr_signal_emit_safe ../util/signal.c:29
    #2 0x7f64009d3c46 in toplevel_decoration_handle_resource_destroy ../types/wlr_xdg_decoration_v1.c:65
    #3 0x7f6400a19f8d  (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x7f8d)
    #4 0x7f6400a19fed in wl_resource_destroy (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x7fed)
    #5 0x7f64009d3d1f in toplevel_decoration_handle_surface_destroy ../types/wlr_xdg_decoration_v1.c:82
    #6 0x7f64009d6f36 in wlr_signal_emit_safe ../util/signal.c:29
    #7 0x7f64009b059c in reset_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:453
    #8 0x7f64009b0688 in destroy_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:483
    #9 0x7f64009af08c in xdg_client_handle_resource_destroy ../types/xdg_shell/wlr_xdg_shell.c:71
    #10 0x7f6400a19f8d  (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x7f8d)
    #11 0x7f6400a1e211  (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0xc211)
    #12 0x7f6400a1e6fe  (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0xc6fe)
    #13 0x7f6400a1a0ec in wl_client_destroy (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x80ec)
    #14 0x7f6400a1a1c4  (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x81c4)
    #15 0x7f6400a1b941 in wl_event_loop_dispatch (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x9941)
    #16 0x7f6400a1a569 in wl_display_run (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x8569)
    #17 0x55571ce4c7fd in server_run ../sway/server.c:214
    #18 0x55571ce4ad59 in main ../sway/main.c:405
    #19 0x7f640071109a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)
    #20 0x55571ce2cfa9 in _start (/usr/local/bin/sway+0x35fa9)

0x615000064d20 is located 32 bytes inside of 504-byte region [0x615000064d00,0x615000064ef8)
freed by thread T0 here:
    #0 0x7f6401531b70 in free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xedb70)
    #1 0x55571ce6c72b in destroy ../sway/desktop/xdg_shell.c:252
    #2 0x55571cee3f7b in view_destroy ../sway/tree/view.c:60
    #3 0x55571cee4090 in view_begin_destroy ../sway/tree/view.c:73
    #4 0x55571ce6dd95 in handle_destroy ../sway/desktop/xdg_shell.c:464
    #5 0x7f64009d6f36 in wlr_signal_emit_safe ../util/signal.c:29
    #6 0x7f64009b059c in reset_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:453
    #7 0x7f64009b0688 in destroy_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:483
    #8 0x7f64009af08c in xdg_client_handle_resource_destroy ../types/xdg_shell/wlr_xdg_shell.c:71
    #9 0x7f6400a19f8d  (/usr/lib/x86_64-linux-gnu/libwayland-server.so.0+0x7f8d)

previously allocated by thread T0 here:
    #0 0x7f6401532138 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xee138)
    #1 0x55571ce6df39 in handle_xdg_shell_surface ../sway/desktop/xdg_shell.c:485
    #2 0x7f64009d6f36 in wlr_signal_emit_safe ../util/signal.c:29
    #3 0x7f64009b0167 in handle_xdg_surface_commit ../types/xdg_shell/wlr_xdg_surface.c:350
    #4 0x7f64009ce2a5 in surface_commit_pending ../types/wlr_surface.c:372
    #5 0x7f64009ce523 in surface_commit ../types/wlr_surface.c:444
    #6 0x7f63ff63ddad in ffi_call_unix64 (/usr/lib/x86_64-linux-gnu/libffi.so.6+0x5dad)

Fixes #3759
---
 sway/desktop/xdg_shell.c | 4 ++++
 sway/xdg_decoration.c    | 4 +++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index ce6fe41a..c84ca111 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -17,6 +17,7 @@
 #include "sway/tree/container.h"
 #include "sway/tree/view.h"
 #include "sway/tree/workspace.h"
+#include "sway/xdg_decoration.h"
 
 static const struct sway_view_child_impl popup_impl;
 
@@ -461,6 +462,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
 	wl_list_remove(&xdg_shell_view->map.link);
 	wl_list_remove(&xdg_shell_view->unmap.link);
 	view->wlr_xdg_surface = NULL;
+	if (view->xdg_decoration) {
+		view->xdg_decoration->view = NULL;
+	}
 	view_begin_destroy(view);
 }
 
diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c
index 39e0df56..9ac87191 100644
--- a/sway/xdg_decoration.c
+++ b/sway/xdg_decoration.c
@@ -10,7 +10,9 @@ static void xdg_decoration_handle_destroy(struct wl_listener *listener,
 		void *data) {
 	struct sway_xdg_decoration *deco =
 		wl_container_of(listener, deco, destroy);
-	deco->view->xdg_decoration = NULL;
+	if(deco->view) {
+		deco->view->xdg_decoration = NULL;
+	}
 	wl_list_remove(&deco->destroy.link);
 	wl_list_remove(&deco->request_mode.link);
 	wl_list_remove(&deco->link);