From b67f94ca7eefdc3ad2a486c4740d1c267255187a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 30 Apr 2024 15:35:14 +0200 Subject: [PATCH] wayland/subsurface: Hold sibling surface reference in placement ops It was possible for the sibling surface to be already destroyed in meta_wayland_transaction_add_placement_surfaces, in which case g_object_ref would return NULL for it, and meta_wayland_transaction_commit would then crash dereferencing a NULL surface pointer. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3462 Part-of: --- src/wayland/meta-wayland-subsurface.c | 12 ++++++++++-- src/wayland/meta-wayland-subsurface.h | 2 ++ src/wayland/meta-wayland-surface.c | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index b88f3d7f4..fd9df170b 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -317,7 +317,6 @@ get_subsurface_placement_op (MetaWaylandSurface *surface, GNode *sibling_node; op->placement = placement; - op->sibling = sibling; op->surface = surface; g_node_unlink (surface->committed_state.subsurface_branch_node); @@ -325,6 +324,8 @@ get_subsurface_placement_op (MetaWaylandSurface *surface, if (!sibling) return op; + op->sibling = g_object_ref (sibling); + if (sibling == parent) sibling_node = parent->committed_state.subsurface_leaf_node; else @@ -347,6 +348,13 @@ get_subsurface_placement_op (MetaWaylandSurface *surface, return op; } +void +meta_wayland_subsurface_destroy_placement_op (MetaWaylandSubsurfacePlacementOp *op) +{ + g_clear_object (&op->sibling); + g_free (op); +} + static void subsurface_place (struct wl_client *client, struct wl_resource *resource, @@ -410,7 +418,7 @@ meta_wayland_subsurface_drop_placement_ops (MetaWaylandSurfaceState *state, if (op->surface == surface) { - g_free (link->data); + meta_wayland_subsurface_destroy_placement_op (op); *list = g_slist_delete_link (*list, link); } else diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h index a4407b7d4..e185bf713 100644 --- a/src/wayland/meta-wayland-subsurface.h +++ b/src/wayland/meta-wayland-subsurface.h @@ -44,6 +44,8 @@ void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, int parent_y, MtkRectangle *out_geometry); +void meta_wayland_subsurface_destroy_placement_op (MetaWaylandSubsurfacePlacementOp *op); + void meta_wayland_subsurface_drop_placement_ops (MetaWaylandSurfaceState *state, MetaWaylandSurface *surface); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 64d94080c..b433a5b1b 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -493,7 +493,8 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) wl_resource_destroy (cb->resource); if (state->subsurface_placement_ops) - g_slist_free_full (state->subsurface_placement_ops, g_free); + g_slist_free_full (state->subsurface_placement_ops, + (GDestroyNotify) meta_wayland_subsurface_destroy_placement_op); meta_wayland_surface_state_discard_presentation_feedback (state); }