From ca3a9478640e6e70b89a988fd0005e6b57b6b35c Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 23 Feb 2018 10:29:18 +0100 Subject: [PATCH] rootston: fix user-after-free in output_handle_destroy --- include/rootston/output.h | 3 ++- rootston/output.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/include/rootston/output.h b/include/rootston/output.h index 9682e4f5..a852a204 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -19,7 +19,8 @@ struct roots_output { struct wlr_output_damage *damage; struct wl_listener destroy; - struct wl_listener frame; + struct wl_listener damage_frame; + struct wl_listener damage_destroy; }; void handle_new_output(struct wl_listener *listener, void *data); diff --git a/rootston/output.c b/rootston/output.c index 8ef383c3..72925f91 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -514,12 +514,6 @@ damage_finish: pixman_region32_fini(&damage); } -static void output_damage_handle_frame(struct wl_listener *listener, - void *data) { - struct roots_output *output = wl_container_of(listener, output, frame); - render_output(output); -} - void output_damage_whole(struct roots_output *output) { wlr_output_damage_add_whole(output->damage); } @@ -681,19 +675,37 @@ static void set_mode(struct wlr_output *output, } } -static void output_handle_destroy(struct wl_listener *listener, void *data) { - struct roots_output *output = wl_container_of(listener, output, destroy); - +static void output_destroy(struct roots_output *output) { // TODO: cursor //example_config_configure_cursor(sample->config, sample->cursor, // sample->compositor); wl_list_remove(&output->link); wl_list_remove(&output->destroy.link); - wl_list_remove(&output->frame.link); + wl_list_remove(&output->damage_frame.link); + wl_list_remove(&output->damage_destroy.link); free(output); } +static void output_handle_destroy(struct wl_listener *listener, void *data) { + struct roots_output *output = wl_container_of(listener, output, destroy); + output_destroy(output); +} + +static void output_damage_handle_frame(struct wl_listener *listener, + void *data) { + struct roots_output *output = + wl_container_of(listener, output, damage_frame); + render_output(output); +} + +static void output_damage_handle_destroy(struct wl_listener *listener, + void *data) { + struct roots_output *output = + wl_container_of(listener, output, damage_destroy); + output_destroy(output); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct roots_desktop *desktop = wl_container_of(listener, desktop, new_output); @@ -722,8 +734,10 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->destroy.notify = output_handle_destroy; wl_signal_add(&wlr_output->events.destroy, &output->destroy); - output->frame.notify = output_damage_handle_frame; - wl_signal_add(&output->damage->events.frame, &output->frame); + output->damage_frame.notify = output_damage_handle_frame; + wl_signal_add(&output->damage->events.frame, &output->damage_frame); + output->damage_destroy.notify = output_damage_handle_destroy; + wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); struct roots_output_config *output_config = roots_config_get_output(config, wlr_output);