From 7678ec9209883600553596160b80f7c8716a5723 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Thu, 29 Sep 2022 13:29:53 +0200 Subject: [PATCH] screenshooter: Add SHM buffer destroy listener to avoid invalid memcpy This adds a destroy listener on the SHM buffer provided by our client. It will unregister the frame notify listener in case our buffer is destroyed before the frame signal is emitted and thus avoid a memcpy to invalid memory. Signed-off-by: Paul Kocialkowski (cherry picked from commit 0afd3428dc899c426d37650192f828541f70e390) --- libweston/screenshooter.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/libweston/screenshooter.c b/libweston/screenshooter.c index b866829b..aaa8de5c 100644 --- a/libweston/screenshooter.c +++ b/libweston/screenshooter.c @@ -45,7 +45,8 @@ #include "wcap/wcap-decode.h" struct screenshooter_frame_listener { - struct wl_listener listener; + struct wl_listener frame_listener; + struct wl_listener buffer_destroy_listener; struct weston_buffer *buffer; struct weston_output *output; weston_screenshooter_done_func_t done; @@ -120,7 +121,8 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data) { struct screenshooter_frame_listener *l = container_of(listener, - struct screenshooter_frame_listener, listener); + struct screenshooter_frame_listener, + frame_listener); struct weston_output *output = l->output; struct weston_compositor *compositor = output->compositor; const pixman_format_code_t pixman_format = @@ -130,6 +132,8 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data) weston_output_disable_planes_decr(output); wl_list_remove(&listener->link); + wl_list_remove(&l->buffer_destroy_listener.link); + stride = l->buffer->width * (PIXMAN_FORMAT_BPP(pixman_format) / 8); pixels = malloc(stride * l->buffer->height); @@ -177,6 +181,22 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data) free(l); } +static void +buffer_destroy_handle(struct wl_listener *listener, void *data) +{ + struct screenshooter_frame_listener *l = + container_of(listener, + struct screenshooter_frame_listener, + buffer_destroy_listener); + + weston_output_disable_planes_decr(l->output); + wl_list_remove(&listener->link); + wl_list_remove(&l->frame_listener.link); + l->done(l->data, WESTON_SCREENSHOOTER_BAD_BUFFER); + + free(l); +} + WL_EXPORT int weston_screenshooter_shoot(struct weston_output *output, struct weston_buffer *buffer, @@ -205,8 +225,13 @@ weston_screenshooter_shoot(struct weston_output *output, l->output = output; l->done = done; l->data = data; - l->listener.notify = screenshooter_frame_notify; - wl_signal_add(&output->frame_signal, &l->listener); + + l->frame_listener.notify = screenshooter_frame_notify; + wl_signal_add(&output->frame_signal, &l->frame_listener); + + l->buffer_destroy_listener.notify = buffer_destroy_handle; + wl_signal_add(&buffer->destroy_signal, &l->buffer_destroy_listener); + weston_output_disable_planes_incr(output); weston_output_schedule_repaint(output);