While the pixman image might be attached, the underlying buffer might be
already gone under certain circumstances. This is easily reproduced by
attempting to resize gnome-terminal on a fbdev backend.

$ WAYLAND_DEBUG=1 strace -emunmap weston --backend=fbdev-backend.so
...
[1524826.942] [email protected]_pool(new id wl_shm_pool@23, fd 40, 1563540)
[1524827.315] [email protected]_buffer(new id wl_buffer@24, 0, 759, 515, 
3036, 0)
...
[1524829.488] [email protected](wl_buffer@24, 0, 0)
[1524829.766] [email protected]_buffer_scale(1)
[1524829.904] [email protected](0, 0, 759, 515)
[1524830.248] [email protected](new id wl_callback@25)
[1524830.450] [email protected]()
...
[1524846.706] [email protected]_pool(new id wl_shm_pool@26, fd 40, 1545000)
[1524847.215] [email protected]_buffer(new id wl_buffer@27, 0, 750, 515, 
3000, 0)
[1524847.735] [email protected]()
[1524847.953]  -> [email protected]_id(24)
[1524848.144] [email protected]()
munmap(0xb5b2e000, 1563540)             = 0
[1524849.021]  -> [email protected]_id(23)
[1524849.425] [email protected](wl_buffer@27, 0, 0)
[1524849.730] [email protected]_buffer_scale(1)
[1524849.821] [email protected](0, 0, 750, 515)
<No commit yet, so drawing is attempted from older buffer that used to be
 attached to the surface, which happens to come from a destroyed pool,
 resulting it an invalid read from address 0xb5b2e000>

Signed-off-by: Lubomir Rintel <[email protected]>
---
Changes to v2:
  - Added listener instead of checking the buffer mapping,
    as suggested by Pekka Paalanen
  - Added more context to the commit message

 src/pixman-renderer.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index b719829..eed1fc2 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -42,6 +42,7 @@ struct pixman_surface_state {
        pixman_image_t *image;
        struct weston_buffer_reference buffer_ref;
 
+       struct wl_listener buffer_destroy_listener;
        struct wl_listener surface_destroy_listener;
        struct wl_listener renderer_destroy_listener;
 };
@@ -450,6 +451,24 @@ pixman_renderer_flush_damage(struct weston_surface 
*surface)
 }
 
 static void
+buffer_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
+{
+       struct pixman_surface_state *ps;
+
+       ps = container_of(listener, struct pixman_surface_state,
+                         buffer_destroy_listener);
+
+       weston_buffer_reference(&ps->buffer_ref, NULL);
+
+       if (ps->image) {
+               pixman_image_unref(ps->image);
+               ps->image = NULL;
+       }
+
+       wl_list_remove(&ps->buffer_destroy_listener.link);
+}
+
+static void
 pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 {
        struct pixman_surface_state *ps = get_surface_state(es);
@@ -459,6 +478,7 @@ pixman_renderer_attach(struct weston_surface *es, struct 
weston_buffer *buffer)
        weston_buffer_reference(&ps->buffer_ref, buffer);
 
        if (ps->image) {
+               wl_list_remove(&ps->buffer_destroy_listener.link);
                pixman_image_unref(ps->image);
                ps->image = NULL;
        }
@@ -499,6 +519,11 @@ pixman_renderer_attach(struct weston_surface *es, struct 
weston_buffer *buffer)
                buffer->width, buffer->height,
                wl_shm_buffer_get_data(shm_buffer),
                wl_shm_buffer_get_stride(shm_buffer));
+
+       ps->buffer_destroy_listener.notify =
+               buffer_state_handle_buffer_destroy;
+       wl_signal_add(&buffer->destroy_signal,
+                     &ps->buffer_destroy_listener);
 }
 
 static void
-- 
1.8.4.2

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to