git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit896773f6e47f5250f15029e313d2bea485e6c87e
parente0d7e4e033
authorIsaac Freund <[email protected]>
date2024-06-13 12:36
SceneNodeData: fix fromSurface() use after free

We must clean up the user data of the wlr_surface for layer surfaces and
lock surfaces as fromSurface() may be called (e.g. by the idle inhibit
implementation) after the scene node has been destroyed but before the
wlr_surface is destroyed.

 river/LayerSurface.zig | 4 +++-
 river/LockSurface.zig  | 3 +++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig
index 03d243d..81dfe57 100644
--- a/river/LayerSurface.zig
+++ b/river/LayerSurface.zig
@@ -55,7 +55,6 @@ pub fn create(wlr_layer_surface: *wlr.LayerSurfaceV1) error{OutOfMemory}!void {
         .scene_layer_surface = try layer_tree.createSceneLayerSurfaceV1(wlr_layer_surface),
         .popup_tree = try output.layers.popups.createSceneTree(),
     };
-    wlr_layer_surface.data = @intFromPtr(layer_surface);
 
     try SceneNodeData.attach(&layer_surface.scene_layer_surface.tree.node, .{ .layer_surface = layer_surface });
     try SceneNodeData.attach(&layer_surface.popup_tree.node, .{ .layer_surface = layer_surface });
@@ -93,6 +92,9 @@ fn handleDestroy(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurfa
 
     layer_surface.popup_tree.node.destroy();
 
+    // The wlr_surface may outlive the wlr_layer_surface so we must clean up the user data.
+    layer_surface.wlr_layer_surface.surface.data = 0;
+
     util.gpa.destroy(layer_surface);
 }
 
diff --git a/river/LockSurface.zig b/river/LockSurface.zig
index c3cd384..60f0aa8 100644
--- a/river/LockSurface.zig
+++ b/river/LockSurface.zig
@@ -85,6 +85,9 @@ pub fn destroy(lock_surface: *LockSurface) void {
     lock_surface.map.link.remove();
     lock_surface.surface_destroy.link.remove();
 
+    // The wlr_surface may outlive the wlr_lock_surface so we must clean up the user data.
+    lock_surface.wlr_lock_surface.surface.data = 0;
+
     util.gpa.destroy(lock_surface);
 }