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 <paul.kocialkowski@bootlin.com>
This commit is contained in:
Paul Kocialkowski 2022-09-29 13:29:53 +02:00
parent 036a76e3eb
commit 0afd3428dc

View file

@ -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);