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>
(cherry picked from commit 0afd3428dc899c426d37650192f828541f70e390)
dev
Paul Kocialkowski 2 years ago committed by Marius Vlad
parent 5517953ed0
commit 7678ec9209
  1. 33
      libweston/screenshooter.c

@ -45,7 +45,8 @@
#include "wcap/wcap-decode.h" #include "wcap/wcap-decode.h"
struct screenshooter_frame_listener { 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_buffer *buffer;
struct weston_output *output; struct weston_output *output;
weston_screenshooter_done_func_t done; weston_screenshooter_done_func_t done;
@ -120,7 +121,8 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
{ {
struct screenshooter_frame_listener *l = struct screenshooter_frame_listener *l =
container_of(listener, container_of(listener,
struct screenshooter_frame_listener, listener); struct screenshooter_frame_listener,
frame_listener);
struct weston_output *output = l->output; struct weston_output *output = l->output;
struct weston_compositor *compositor = output->compositor; struct weston_compositor *compositor = output->compositor;
const pixman_format_code_t pixman_format = 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); weston_output_disable_planes_decr(output);
wl_list_remove(&listener->link); wl_list_remove(&listener->link);
wl_list_remove(&l->buffer_destroy_listener.link);
stride = l->buffer->width * (PIXMAN_FORMAT_BPP(pixman_format) / 8); stride = l->buffer->width * (PIXMAN_FORMAT_BPP(pixman_format) / 8);
pixels = malloc(stride * l->buffer->height); pixels = malloc(stride * l->buffer->height);
@ -177,6 +181,22 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
free(l); 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 WL_EXPORT int
weston_screenshooter_shoot(struct weston_output *output, weston_screenshooter_shoot(struct weston_output *output,
struct weston_buffer *buffer, struct weston_buffer *buffer,
@ -205,8 +225,13 @@ weston_screenshooter_shoot(struct weston_output *output,
l->output = output; l->output = output;
l->done = done; l->done = done;
l->data = data; 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_disable_planes_incr(output);
weston_output_schedule_repaint(output); weston_output_schedule_repaint(output);

Loading…
Cancel
Save