wayland: fix use-after-free of WDock during clip restore
ASan caught it: heap-use-after-free at wl_clip_icon_paint:8478 reading
workspace->clip->collapsed. The flow is:
wWorkspaceRestoreState()
if (scr->workspaces[i]->clip)
wDockDestroy(scr->workspaces[i]->clip); // frees the WDock
scr->workspaces[i]->clip = wDockRestoreState(); // creates new
wDockCreate -> dockIconPaint -> wClipIconPaint
-> wl_clip_icon_paint
workspace->clip->collapsed // ← reads freed pointer
scr->workspaces[i]->clip is dangling between the wDockDestroy and the
assignment from wDockRestoreState. wl_clip_icon_paint runs inside
that gap (wDockCreate calls dockIconPaint via wClipIconPaint).
Fix: read collapsed state from aicon->dock instead of workspace->clip.
aicon->dock is the dock currently being constructed and is always
valid at this point.
This was masquerading as a 'double free' on right-click of titlebars
(the heap corruption from the early use-after-free corrupted later
allocations that pixman_image_unref then tripped over). Removed
the diagnostic logs added while debugging.
This commit is contained in:
parent
bf56ccb8eb
commit
d6e10203fa
|
|
@ -3986,7 +3986,6 @@ wl_show_crash_dialog(int sig)
|
|||
static void frame_buf_destroy(struct wlr_buffer *wlr_buf)
|
||||
{
|
||||
struct wl_frame_buf *fb = wl_container_of(wlr_buf, fb, base);
|
||||
wwarning("FBDESTROY: id=0x%lx fb=%p fb->image=%p", fb->id, (void*)fb, fb->image);
|
||||
if (fb->image)
|
||||
pixman_image_unref(fb->image);
|
||||
wfree(fb);
|
||||
|
|
@ -4357,15 +4356,10 @@ wl_frame_configure(WNativeWindow win, int x, int y, int width, int height)
|
|||
|
||||
/* Resize: reallocate the pixman image if dimensions changed. */
|
||||
if (width > 0 && height > 0 && (width != fb->width || height != fb->height)) {
|
||||
wwarning("FCFG: id=0x%lx fb->image=%p old_size=%dx%d new_size=%dx%d "
|
||||
"scene_buf=%p tree=%p parent_id=0x%lx",
|
||||
fb->id, fb->image, fb->width, fb->height, width, height,
|
||||
fb->scene_buf, fb->tree, fb->parent_id);
|
||||
pixman_image_t *old_image = fb->image;
|
||||
if (fb->image)
|
||||
pixman_image_unref(fb->image);
|
||||
fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8,
|
||||
width, height, NULL, 0);
|
||||
/* Update fb metadata BEFORE notifying wlroots so it sees the
|
||||
* new size when accessing the buffer. */
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
fb->base.width = width;
|
||||
|
|
@ -4375,11 +4369,6 @@ wl_frame_configure(WNativeWindow win, int x, int y, int width, int height)
|
|||
* the old size would miss this scene_buf. */
|
||||
if (fb->scene_buf)
|
||||
wlr_scene_buffer_set_dest_size(fb->scene_buf, width, height);
|
||||
/* Now drop the old image — wlroots will not access it again
|
||||
* because we already pointed it to the new one above (via
|
||||
* fb->image which is what begin_data_ptr_access reads). */
|
||||
if (old_image)
|
||||
pixman_image_unref(old_image);
|
||||
}
|
||||
|
||||
/* Update absolute position tracking — recursively for all descendants. */
|
||||
|
|
@ -8481,8 +8470,13 @@ static void wl_clip_icon_paint(WAppIcon *aicon)
|
|||
return;
|
||||
|
||||
WWorkspace *workspace = scr->workspaces[scr->current_workspace];
|
||||
/* Use aicon->dock to read collapsed state — workspace->clip may be a
|
||||
* stale freed pointer during wWorkspaceRestoreState (the old clip is
|
||||
* destroyed before scr->workspaces[i]->clip is reassigned, and we
|
||||
* are called from wDockCreate inside that gap). */
|
||||
int collapsed = aicon->dock ? aicon->dock->collapsed : 0;
|
||||
WMColor *color;
|
||||
if (wPreferences.flags.noclip || !workspace->clip->collapsed)
|
||||
if (wPreferences.flags.noclip || !collapsed)
|
||||
color = scr->clip_title_color[CLIP_NORMAL];
|
||||
else
|
||||
color = scr->clip_title_color[CLIP_COLLAPSED];
|
||||
|
|
|
|||
Loading…
Reference in New Issue