xserver: Branch 'master' - 5 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jul 4 08:29:51 UTC 2024


 hw/xwayland/xwayland-dmabuf.c         |    2 -
 hw/xwayland/xwayland-window-buffers.c |   35 ++++++++++++++------
 hw/xwayland/xwayland-window-buffers.h |    2 -
 hw/xwayland/xwayland-window.c         |   57 ++++++++++++++++++++--------------
 4 files changed, 61 insertions(+), 35 deletions(-)

New commits:
commit a5e863963e3d8cef2cf84f7c65832adb78040798
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jul 2 18:54:10 2024 +0200

    xwayland: Force disposal of windows buffers for root on destroy
    
    With explicit buffer synchronization in use, the window buffers use a
    file descriptor for event notification to keep the buffer alive for
    synchronization purpose.
    
    When running rootful, the root window (which is visible) is destroyed
    directly from the resource manager on server reset, and the window
    buffer's eventfd will trigger after the window is destroyed, leading to
    a use after free and a crash of the xserver.
    
    To avoid the issue, check whether the window being destroyed is the root
    window in rootless mode, and make sure to force the disposal of the
    window buffers in that case.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1699
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1589>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 2c5d68bd4..6fe0db891 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1649,6 +1649,7 @@ xwl_window_dispose(struct xwl_window *xwl_window)
     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
     struct xwl_seat *xwl_seat;
     WindowPtr window = xwl_window->toplevel;
+    ScreenPtr screen = xwl_screen->screen;
 
     compUnredirectWindow(serverClient, window, CompositeRedirectManual);
 
@@ -1691,7 +1692,9 @@ xwl_window_dispose(struct xwl_window *xwl_window)
     xorg_list_del(&xwl_window->link_damage);
     xorg_list_del(&xwl_window->link_window);
 
-    xwl_window_buffers_dispose(xwl_window, FALSE);
+    /* Special case for the root window in rootful mode */
+    xwl_window_buffers_dispose(xwl_window,
+                               (!xwl_screen->rootless && window == screen->root));
 
     if (xwl_window->window_buffers_timer)
         TimerFree(xwl_window->window_buffers_timer);
commit fa04e15afccc8ef49a00e39c84e26b2f7fca5966
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jul 2 18:51:44 2024 +0200

    xwayland/window-buffers: optionally force disposal
    
    For cases (to come) where we would want to force the disposal of the
    window buffers, add a parameter to force the disposal by calling
    dispose() directly instead of maybe_dispose().
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1589>

diff --git a/hw/xwayland/xwayland-dmabuf.c b/hw/xwayland/xwayland-dmabuf.c
index db7dc44ee..e485e5b1c 100644
--- a/hw/xwayland/xwayland-dmabuf.c
+++ b/hw/xwayland/xwayland-dmabuf.c
@@ -752,7 +752,7 @@ xwl_window_dmabuf_feedback_done(void *data,
     /* If the linux-dmabuf v4 per-surface feedback changed, make sure the
      * window buffers get re-created with appropriate parameters.
      */
-    xwl_window_buffers_dispose(xwl_window);
+    xwl_window_buffers_dispose(xwl_window, FALSE);
     xwl_window_realloc_pixmap(xwl_window);
 }
 
diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 1a7e78537..2bf6c978c 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -244,8 +244,17 @@ xwl_window_buffers_init(struct xwl_window *xwl_window)
     xorg_list_init(&xwl_window->window_buffers_unavailable);
 }
 
+static void
+xwl_window_buffer_disposal(struct xwl_window_buffer *xwl_window_buffer, Bool force)
+{
+    if (force)
+        xwl_window_buffer_dispose(xwl_window_buffer);
+    else
+        xwl_window_buffer_maybe_dispose(xwl_window_buffer);
+}
+
 void
-xwl_window_buffers_dispose(struct xwl_window *xwl_window)
+xwl_window_buffers_dispose(struct xwl_window *xwl_window, Bool force)
 {
     struct xwl_window_buffer *xwl_window_buffer, *tmp;
 
@@ -257,14 +266,14 @@ xwl_window_buffers_dispose(struct xwl_window *xwl_window)
                                   &xwl_window->window_buffers_available,
                                   link_buffer) {
         xorg_list_del(&xwl_window_buffer->link_buffer);
-        xwl_window_buffer_maybe_dispose(xwl_window_buffer);
+        xwl_window_buffer_disposal(xwl_window_buffer, force);
     }
 
     xorg_list_for_each_entry_safe(xwl_window_buffer, tmp,
                                   &xwl_window->window_buffers_unavailable,
                                   link_buffer) {
         xorg_list_del(&xwl_window_buffer->link_buffer);
-        xwl_window_buffer_maybe_dispose(xwl_window_buffer);
+        xwl_window_buffer_disposal(xwl_window_buffer, force);
     }
 
     if (xwl_window->window_buffers_timer)
diff --git a/hw/xwayland/xwayland-window-buffers.h b/hw/xwayland/xwayland-window-buffers.h
index af46eb91b..dabb343c1 100644
--- a/hw/xwayland/xwayland-window-buffers.h
+++ b/hw/xwayland/xwayland-window-buffers.h
@@ -34,7 +34,7 @@
 void xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window);
 void xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer);
 void xwl_window_buffers_init(struct xwl_window *xwl_window);
-void xwl_window_buffers_dispose(struct xwl_window *xwl_window);
+void xwl_window_buffers_dispose(struct xwl_window *xwl_window, Bool force);
 void xwl_window_realloc_pixmap(struct xwl_window *xwl_window);
 PixmapPtr xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync);
 
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 7549d4fad..2c5d68bd4 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1407,7 +1407,7 @@ xwl_window_update_surface_window(struct xwl_window *xwl_window)
     }
 
     if (surface_window->drawable.depth != xwl_window->surface_window->drawable.depth)
-        xwl_window_buffers_dispose(xwl_window);
+        xwl_window_buffers_dispose(xwl_window, FALSE);
 
     xwl_window->surface_window = surface_window;
     register_damage(xwl_window);
@@ -1691,7 +1691,7 @@ xwl_window_dispose(struct xwl_window *xwl_window)
     xorg_list_del(&xwl_window->link_damage);
     xorg_list_del(&xwl_window->link_window);
 
-    xwl_window_buffers_dispose(xwl_window);
+    xwl_window_buffers_dispose(xwl_window, FALSE);
 
     if (xwl_window->window_buffers_timer)
         TimerFree(xwl_window->window_buffers_timer);
@@ -1753,7 +1753,7 @@ xwl_window_set_window_pixmap(WindowPtr window,
          old_pixmap->drawable.height == pixmap->drawable.height))
        return;
 
-    xwl_window_buffers_dispose(xwl_window);
+    xwl_window_buffers_dispose(xwl_window, FALSE);
 }
 
 Bool
commit 571cb1334274add24d77b2576001f2703b188b41
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Tue Jul 2 18:49:14 2024 +0200

    xwayland/window-buffers: Move buffer disposal to its own function
    
    No functional change, this is just preparation work for the next commit.
    
    v2: Reshuffle functions (Michel)
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1589>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 8c8475c0b..1a7e78537 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -102,14 +102,9 @@ xwl_window_buffer_destroy_pixmap(struct xwl_window_buffer *xwl_window_buffer)
     xwl_window_buffer->pixmap = NullPixmap;
 }
 
-static Bool
-xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer)
+static void
+xwl_window_buffer_dispose(struct xwl_window_buffer *xwl_window_buffer)
 {
-    assert(xwl_window_buffer->refcnt > 0);
-
-    if (--xwl_window_buffer->refcnt)
-        return FALSE;
-
     RegionDestroy(xwl_window_buffer->damage_region);
 
     if (xwl_window_buffer->pixmap) {
@@ -121,6 +116,17 @@ xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer)
 
     xorg_list_del(&xwl_window_buffer->link_buffer);
     free(xwl_window_buffer);
+}
+
+static Bool
+xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer)
+{
+    assert(xwl_window_buffer->refcnt > 0);
+
+    if (--xwl_window_buffer->refcnt)
+        return FALSE;
+
+    xwl_window_buffer_dispose(xwl_window_buffer);
 
     return TRUE;
 }
commit 0e1a98f52f57111c7259244be86bec92de27b3ce
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Jul 3 09:55:43 2024 +0200

    xwayland: Make sure we do not leak xwl_window on destroy
    
    Right now, we would dispose the xwl_window and all the data associated
    with it on unrealize.
    
    But not all window destruction go through the unrealize code path, for
    example when the root window (running rootful) is destroyed from the
    resource manager on server reset, we do not get to the unrealize window
    step, but straight to destroy window.
    
    As a result, we are leaking the xwl_window and all the data associated
    with it, for example:
    
    | 65,536 bytes in 1 blocks are possibly lost in loss record 12,462 of 12,488
    |    at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
    |    by 0x48B661C: UnknownInlinedFun (pixman-bits-image.c:1273)
    |    by 0x48B661C: _pixman_bits_image_init (pixman-bits-image.c:1296)
    |    by 0x48B6754: create_bits_image_internal (pixman-bits-image.c:1349)
    |    by 0x64180DE: UnknownInlinedFun (cairo-image-surface.c:380)
    |    by 0x64180DE: UnknownInlinedFun (cairo-image-surface.c:366)
    |    by 0x64180DE: cairo_image_surface_create (cairo-image-surface.c:432)
    |    by 0x6346B44: UnknownInlinedFun (libdecor-gtk.c:467)
    |    by 0x6346B44: libdecor_plugin_gtk_frame_new (libdecor-gtk.c:546)
    |    by 0x4B7F297: libdecor_decorate (libdecor.c:559)
    |    by 0x42C6F3: xwl_create_root_surface (xwayland-window.c:1266)
    |    by 0x42CD97: ensure_surface_for_window (xwayland-window.c:1466)
    |    by 0x42D0D1: xwl_realize_window (xwayland-window.c:1560)
    |    by 0x50858F: compRealizeWindow (compwindow.c:279)
    |    by 0x4FF2A2: MapWindow (window.c:2706)
    |    by 0x4F9E7F: InitRootWindow (window.c:697)
    
    To avoid that issue, check whether there is still an xwl_window
    associated with the X11 window on destroy, and if that's the case,
    dispose the xwl_window.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1589>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index a04801bae..7549d4fad 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1930,11 +1930,15 @@ xwl_destroy_window(WindowPtr window)
 {
     ScreenPtr screen = window->drawable.pScreen;
     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_window *xwl_window = xwl_window_get(window);
     Bool ret;
 
     if (xwl_screen->present)
         xwl_present_cleanup(window);
 
+    if (xwl_window)
+        xwl_window_dispose(xwl_window);
+
     screen->DestroyWindow = xwl_screen->DestroyWindow;
 
     if (screen->DestroyWindow)
commit 74be7a7f36b57238df9830aed3dc5f8fc2bbbd3d
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Jul 3 09:52:28 2024 +0200

    xwayland: Move xwl_window disposal to its own function
    
    No functional change intended, this is just preparation work for the
    next commit.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1589>

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 90ece334a..a04801bae 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1643,28 +1643,14 @@ release_wl_surface_for_window(struct xwl_window *xwl_window)
         release_wl_surface_for_window_legacy_delay(xwl_window);
 }
 
-Bool
-xwl_unrealize_window(WindowPtr window)
+static void
+xwl_window_dispose(struct xwl_window *xwl_window)
 {
-    ScreenPtr screen = window->drawable.pScreen;
-    struct xwl_screen *xwl_screen;
-    struct xwl_window *xwl_window;
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
     struct xwl_seat *xwl_seat;
-    Bool ret;
-
-    xwl_screen = xwl_screen_get(screen);
+    WindowPtr window = xwl_window->toplevel;
 
-    xwl_window = xwl_window_get(window);
-    if (xwl_window)
-        compUnredirectWindow(serverClient, window, CompositeRedirectManual);
-
-    screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
-    ret = (*screen->UnrealizeWindow) (window);
-    xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
-    screen->UnrealizeWindow = xwl_unrealize_window;
-
-    if (!xwl_window)
-        return ret;
+    compUnredirectWindow(serverClient, window, CompositeRedirectManual);
 
     xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
         if (xwl_seat->focus_window == xwl_window)
@@ -1704,7 +1690,6 @@ xwl_unrealize_window(WindowPtr window)
     release_wl_surface_for_window(xwl_window);
     xorg_list_del(&xwl_window->link_damage);
     xorg_list_del(&xwl_window->link_window);
-    unregister_damage(xwl_window);
 
     xwl_window_buffers_dispose(xwl_window);
 
@@ -1718,6 +1703,25 @@ xwl_unrealize_window(WindowPtr window)
 
     free(xwl_window);
     dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
+}
+
+Bool
+xwl_unrealize_window(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_window *xwl_window = xwl_window_get(window);
+    Bool ret;
+
+    if (xwl_window) {
+        unregister_damage(xwl_window);
+        xwl_window_dispose(xwl_window);
+    }
+
+    screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
+    ret = (*screen->UnrealizeWindow) (window);
+    xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
+    screen->UnrealizeWindow = xwl_unrealize_window;
 
     return ret;
 }


More information about the xorg-commit mailing list