xwayland: avoid using freed xwl_window on unrealize
xwl_unrealize_window() would use freed xwl_window which can lead to
various memory corruption and crashes, as reported by valgrind:
Invalid read of size 8
at 0x42C802: xwl_present_cleanup (xwayland-present.c:84)
by 0x42BA67: xwl_unrealize_window (xwayland.c:601)
by 0x541EE9: compUnrealizeWindow (compwindow.c:285)
by 0x57E1FA: UnrealizeTree (window.c:2816)
by 0x581189: UnmapWindow (window.c:2874)
by 0x54EB26: ProcUnmapWindow (dispatch.c:879)
by 0x554B7D: Dispatch (dispatch.c:479)
by 0x558BE5: dix_main (main.c:276)
by 0x7C4B1BA: (below main) (libc-start.c:308)
Address 0xf520f60 is 96 bytes inside a block of size 184 free'd
at 0x4C2EDAC: free (vg_replace_malloc.c:530)
by 0x42B9FB: xwl_unrealize_window (xwayland.c:624)
by 0x541EE9: compUnrealizeWindow (compwindow.c:285)
by 0x57E1FA: UnrealizeTree (window.c:2816)
by 0x581189: UnmapWindow (window.c:2874)
by 0x54EB26: ProcUnmapWindow (dispatch.c:879)
by 0x554B7D: Dispatch (dispatch.c:479)
by 0x558BE5: dix_main (main.c:276)
by 0x7C4B1BA: (below main) (libc-start.c:308)
Block was alloc'd at
at 0x4C2FB06: calloc (vg_replace_malloc.c:711)
by 0x42B307: xwl_realize_window (xwayland.c:488)
by 0x541E59: compRealizeWindow (compwindow.c:268)
by 0x57DA40: RealizeTree (window.c:2617)
by 0x580B28: MapWindow (window.c:2694)
by 0x54EA2A: ProcMapWindow (dispatch.c:845)
by 0x554B7D: Dispatch (dispatch.c:479)
by 0x558BE5: dix_main (main.c:276)
by 0x7C4B1BA: (below main) (libc-start.c:308)
This is because UnrealizeTree() traverses the tree from top to bottom,
which invalidates the assumption that if the Window doesn't feature an
xwl_window on its own, it's the xwl_window of its first ancestor with
one.
This reverts commit 82df2ce3
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
parent
12a6b189fb
commit
8b8f9007cc
|
@ -1067,7 +1067,7 @@ xwl_keyboard_activate_grab(DeviceIntPtr device, GrabPtr grab, TimeStamp time, Bo
|
|||
if (xwl_seat == NULL)
|
||||
xwl_seat = find_matching_seat(device);
|
||||
if (xwl_seat)
|
||||
set_grab(xwl_seat, xwl_window_of_top(grab->window));
|
||||
set_grab(xwl_seat, xwl_window_from_window(grab->window));
|
||||
}
|
||||
|
||||
ActivateKeyboardGrab(device, grab, time, passive);
|
||||
|
|
|
@ -73,13 +73,9 @@ xwl_present_reset_timer(struct xwl_window *xwl_window)
|
|||
}
|
||||
|
||||
void
|
||||
xwl_present_cleanup(WindowPtr window)
|
||||
xwl_present_cleanup(struct xwl_window *xwl_window, WindowPtr window)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(window);
|
||||
struct xwl_present_event *event, *tmp;
|
||||
|
||||
if (!xwl_window)
|
||||
return;
|
||||
struct xwl_present_event *event, *tmp;
|
||||
|
||||
if (xwl_window->present_window == window) {
|
||||
if (xwl_window->present_frame_callback) {
|
||||
|
@ -91,18 +87,14 @@ xwl_present_cleanup(WindowPtr window)
|
|||
|
||||
/* Clear remaining events */
|
||||
xorg_list_for_each_entry_safe(event, tmp, &xwl_window->present_event_list, list) {
|
||||
if (event->present_window == window) {
|
||||
xorg_list_del(&event->list);
|
||||
free(event);
|
||||
}
|
||||
xorg_list_del(&event->list);
|
||||
free(event);
|
||||
}
|
||||
|
||||
/* Clear remaining buffer releases and inform Present about free ressources */
|
||||
xorg_list_for_each_entry_safe(event, tmp, &xwl_window->present_release_queue, list) {
|
||||
if (event->present_window == window) {
|
||||
xorg_list_del(&event->list);
|
||||
event->abort = TRUE;
|
||||
}
|
||||
xorg_list_del(&event->list);
|
||||
event->abort = TRUE;
|
||||
}
|
||||
|
||||
/* Clear timer */
|
||||
|
@ -258,7 +250,7 @@ static const struct wl_callback_listener xwl_present_sync_listener = {
|
|||
static RRCrtcPtr
|
||||
xwl_present_get_crtc(WindowPtr present_window)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
if (xwl_window == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -268,7 +260,7 @@ xwl_present_get_crtc(WindowPtr present_window)
|
|||
static int
|
||||
xwl_present_get_ust_msc(WindowPtr present_window, uint64_t *ust, uint64_t *msc)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
if (!xwl_window)
|
||||
return BadAlloc;
|
||||
*ust = xwl_window->present_ust;
|
||||
|
@ -297,7 +289,7 @@ xwl_present_queue_vblank(WindowPtr present_window,
|
|||
uint64_t event_id,
|
||||
uint64_t msc)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
struct xwl_present_event *event;
|
||||
|
||||
if (!xwl_window)
|
||||
|
@ -337,7 +329,7 @@ xwl_present_abort_vblank(WindowPtr present_window,
|
|||
uint64_t event_id,
|
||||
uint64_t msc)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
struct xwl_present_event *event, *tmp;
|
||||
|
||||
if (!xwl_window)
|
||||
|
@ -374,7 +366,7 @@ xwl_present_check_flip2(RRCrtcPtr crtc,
|
|||
Bool sync_flip,
|
||||
PresentFlipReason *reason)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
|
||||
if (!xwl_window)
|
||||
return FALSE;
|
||||
|
@ -415,7 +407,7 @@ xwl_present_flip(WindowPtr present_window,
|
|||
Bool sync_flip,
|
||||
RegionPtr damage)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
BoxPtr present_box, damage_box;
|
||||
Bool buffer_created;
|
||||
struct wl_buffer *buffer;
|
||||
|
@ -485,7 +477,7 @@ xwl_present_flip(WindowPtr present_window,
|
|||
static void
|
||||
xwl_present_flips_stop(WindowPtr window)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_of_top(window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(window);
|
||||
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
|
|
@ -122,23 +122,12 @@ static DevPrivateKeyRec xwl_window_private_key;
|
|||
static DevPrivateKeyRec xwl_screen_private_key;
|
||||
static DevPrivateKeyRec xwl_pixmap_private_key;
|
||||
|
||||
struct xwl_window *
|
||||
xwl_window_of_top(WindowPtr window)
|
||||
static struct xwl_window *
|
||||
xwl_window_get(WindowPtr window)
|
||||
{
|
||||
return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
|
||||
}
|
||||
|
||||
static struct xwl_window *
|
||||
xwl_window_of_self(WindowPtr window)
|
||||
{
|
||||
struct xwl_window *xwl_window = dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
|
||||
|
||||
if (xwl_window && xwl_window->window == window)
|
||||
return xwl_window;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct xwl_screen *
|
||||
xwl_screen_get(ScreenPtr screen)
|
||||
{
|
||||
|
@ -223,7 +212,7 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
|||
if (rec->win->drawable.pScreen != screen)
|
||||
return;
|
||||
|
||||
xwl_window = xwl_window_of_self(rec->win);
|
||||
xwl_window = xwl_window_get(rec->win);
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
|
@ -262,6 +251,22 @@ xwl_close_screen(ScreenPtr screen)
|
|||
return screen->CloseScreen(screen);
|
||||
}
|
||||
|
||||
struct xwl_window *
|
||||
xwl_window_from_window(WindowPtr window)
|
||||
{
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
while (window) {
|
||||
xwl_window = xwl_window_get(window);
|
||||
if (xwl_window)
|
||||
return xwl_window;
|
||||
|
||||
window = window->parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct xwl_seat *
|
||||
xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
|
@ -292,7 +297,7 @@ xwl_cursor_warped_to(DeviceIntPtr device,
|
|||
if (!window)
|
||||
window = XYToWindow(sprite, x, y);
|
||||
|
||||
xwl_window = xwl_window_of_top(window);
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window && xwl_seat->focus_window) {
|
||||
focus = xwl_seat->focus_window->window;
|
||||
|
||||
|
@ -339,7 +344,7 @@ xwl_cursor_confined_to(DeviceIntPtr device,
|
|||
return;
|
||||
}
|
||||
|
||||
xwl_window = xwl_window_of_top(window);
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window && xwl_seat->focus_window) {
|
||||
/* Allow confining on InputOnly windows, but only if the geometry
|
||||
* is the same than the focus window.
|
||||
|
@ -455,7 +460,6 @@ xwl_realize_window(WindowPtr window)
|
|||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_window *xwl_window;
|
||||
struct wl_region *region;
|
||||
Bool create_xwl_window = TRUE;
|
||||
Bool ret;
|
||||
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
@ -475,17 +479,11 @@ xwl_realize_window(WindowPtr window)
|
|||
|
||||
if (xwl_screen->rootless) {
|
||||
if (window->redirectDraw != RedirectDrawManual)
|
||||
create_xwl_window = FALSE;
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
if (window->parent)
|
||||
create_xwl_window = FALSE;
|
||||
}
|
||||
|
||||
if (!create_xwl_window) {
|
||||
if (window->parent)
|
||||
dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window_of_top(window->parent));
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
xwl_window = calloc(1, sizeof *xwl_window);
|
||||
|
@ -602,9 +600,9 @@ xwl_unrealize_window(WindowPtr window)
|
|||
compUnredirectWindow(serverClient, window, CompositeRedirectManual);
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_screen->present)
|
||||
/* Always cleanup Present (Present might have been active on child window) */
|
||||
xwl_present_cleanup(window);
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (xwl_window && xwl_screen->present)
|
||||
xwl_present_cleanup(xwl_window, window);
|
||||
#endif
|
||||
|
||||
screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
|
||||
|
@ -612,11 +610,9 @@ xwl_unrealize_window(WindowPtr window)
|
|||
xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
|
||||
screen->UnrealizeWindow = xwl_unrealize_window;
|
||||
|
||||
xwl_window = xwl_window_of_self(window);
|
||||
if (!xwl_window) {
|
||||
dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
|
||||
xwl_window = xwl_window_get(window);
|
||||
if (!xwl_window)
|
||||
return ret;
|
||||
}
|
||||
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
|
|
|
@ -361,7 +361,7 @@ RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
|
|||
void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap);
|
||||
struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap);
|
||||
|
||||
struct xwl_window *xwl_window_of_top(WindowPtr window);
|
||||
struct xwl_window *xwl_window_from_window(WindowPtr window);
|
||||
|
||||
Bool xwl_shm_create_screen_resources(ScreenPtr screen);
|
||||
PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height,
|
||||
|
@ -383,7 +383,7 @@ struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
|
|||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
Bool xwl_present_init(ScreenPtr screen);
|
||||
void xwl_present_cleanup(WindowPtr window);
|
||||
void xwl_present_cleanup(struct xwl_window *xwl_window, WindowPtr window);
|
||||
#endif
|
||||
|
||||
void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen);
|
||||
|
|
Loading…
Reference in New Issue