[PATCH xserver v3] xwayland: Fix use after free of cursors
Olivier Fourdan
ofourdan at redhat.com
Wed Nov 23 08:51:58 UTC 2016
> Sometimes, Xwayland will try to use a cursor that has just been freed,
> leading to a crash when trying to access that cursor data either in
> miPointerUpdateSprite() or AnimCurTimerNotify().
>
> CheckMotion() updates the pointer's cursor based on which xwindow
> XYToWindow() returns, and Xwayland implements its own xwl_xy_to_window()
> to fake a crossing to the root window when the pointer has left the
> Wayland surface but is still within the xwindow.
>
> But after an xwindow is unrealized, the last xwindow used to match the
> xwindows is cleared so two consecutive calls to xwl_xy_to_window() may
> not return the same xwindow.
>
> To avoid this issue, update the last_xwindow based on enter and leave
> notifications instead of xwl_xy_to_window(), and check if the xwindow
> found by the regular miXYToWindow() is a child of the known last
> xwindow, so that multiple consecutive calls to xwl_xy_to_window()
> return the same xwindow, being either the one found by miXYToWindow()
> or the root window.
>
> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1385258
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
Tested-by: Vít Ondruch <vondruch at redhat.com>
Tested-by: Satish Balay <balay at fastmail.fm>
> ---
> v2: Issue was caused by inconsistent returned value from
> xwl_xy_to_window() after a window is unrealized, fix the
> issue to update the last_xwindow on enter/leave notify handlers.
> Fix was succesfully tested in:
> https://bugzilla.redhat.com/show_bug.cgi?id=1387281
> v3: Same patch, reword the commit messag to make it shorter and clearer
> (apparently patchwork did not like the long message much...)
>
> hw/xwayland/xwayland-input.c | 17 +++++++++++++----
> 1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
> index 0526122..681bc9d 100644
> --- a/hw/xwayland/xwayland-input.c
> +++ b/hw/xwayland/xwayland-input.c
> @@ -312,6 +312,9 @@ pointer_handle_enter(void *data, struct wl_pointer
> *pointer,
> dx = xwl_seat->focus_window->window->drawable.x;
> dy = xwl_seat->focus_window->window->drawable.y;
>
> + /* We just entered a new xwindow, forget about the old last xwindow */
> + xwl_seat->last_xwindow = NullWindow;
> +
> master = GetMaster(dev, POINTER_OR_FLOAT);
> (*pScreen->SetCursorPosition) (dev, pScreen, dx + sx, dy + sy, TRUE);
>
> @@ -360,8 +363,14 @@ pointer_handle_leave(void *data, struct wl_pointer
> *pointer,
>
> xwl_seat->xwl_screen->serial = serial;
>
> - xwl_seat->focus_window = NULL;
> - CheckMotion(NULL, GetMaster(dev, POINTER_OR_FLOAT));
> + /* The pointer has left a known xwindow, save it for a possible match
> + * in sprite_check_lost_focus()
> + */
> + if (xwl_seat->focus_window) {
> + xwl_seat->last_xwindow = xwl_seat->focus_window->window;
> + xwl_seat->focus_window = NULL;
> + CheckMotion(NULL, GetMaster(dev, POINTER_OR_FLOAT));
> + }
> }
>
> static void
> @@ -1256,10 +1265,10 @@ sprite_check_lost_focus(SpritePtr sprite, WindowPtr
> window)
> */
> if (master->lastSlave == xwl_seat->pointer &&
> xwl_seat->focus_window == NULL &&
> - xwl_seat->last_xwindow == window)
> + xwl_seat->last_xwindow != NullWindow &&
> + IsParent (xwl_seat->last_xwindow, window))
> return TRUE;
>
> - xwl_seat->last_xwindow = window;
> return FALSE;
> }
>
> --
> 2.9.3
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel
More information about the xorg-devel
mailing list