compositor: fix wp_viewport use after free
If a client destroyed the wl_surface before the wp_viewport, Weston core would access freed memory, because the weston_surface pointer stored in the wp_viewport wl_resource's user data was stale. Fix this by setting the user data to NULL on wl_surface destruction. It is specifically about wl_surface and not weston_surface destruction, because this is about client-visible behaviour. Something internal might keep weston_surface alive past the wl_surface. Add checks to all wp_viewport request handlers. At the same time, implement the new error conditions in wp_viewport: calling any request except destroy must result in a protocol error. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
This commit is contained in:
parent
eaf406190a
commit
4826f87605
@ -1852,6 +1852,10 @@ destroy_surface(struct wl_resource *resource)
|
||||
* dangling pointer if the surface was refcounted and survives
|
||||
* the weston_surface_destroy() call. */
|
||||
surface->resource = NULL;
|
||||
|
||||
if (surface->viewport_resource)
|
||||
wl_resource_set_user_data(surface->viewport_resource, NULL);
|
||||
|
||||
weston_surface_destroy(surface);
|
||||
}
|
||||
|
||||
@ -4219,6 +4223,9 @@ destroy_viewport(struct wl_resource *resource)
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(resource);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
surface->viewport_resource = NULL;
|
||||
surface->pending.buffer_viewport.buffer.src_width =
|
||||
wl_fixed_from_int(-1);
|
||||
@ -4244,7 +4251,14 @@ viewport_set_source(struct wl_client *client,
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(resource);
|
||||
|
||||
assert(surface->viewport_resource != NULL);
|
||||
if (!surface) {
|
||||
wl_resource_post_error(resource,
|
||||
WP_VIEWPORT_ERROR_NO_SURFACE,
|
||||
"wl_surface for this viewport is no longer exists");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(surface->viewport_resource == resource);
|
||||
|
||||
if (src_width == wl_fixed_from_int(-1) &&
|
||||
src_height == wl_fixed_from_int(-1)) {
|
||||
@ -4280,7 +4294,14 @@ viewport_set_destination(struct wl_client *client,
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(resource);
|
||||
|
||||
assert(surface->viewport_resource != NULL);
|
||||
if (!surface) {
|
||||
wl_resource_post_error(resource,
|
||||
WP_VIEWPORT_ERROR_NO_SURFACE,
|
||||
"wl_surface for this viewport no longer exists");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(surface->viewport_resource == resource);
|
||||
|
||||
if (dst_width == -1 && dst_height == -1) {
|
||||
/* unset destination size */
|
||||
|
Loading…
x
Reference in New Issue
Block a user