Skip to content

(release/25.2) rootless: fix dangling screen pixmap on RootlessUpdateScreenPixmap() OOM - #3507

Open
metux wants to merge 1 commit into
release/25.2from
pr/release/25.2-rootless-fix-dangling-screen-pixmap-on-rootlessupdatescreenpixmap-oom_2026-08-07_14-53-37
Open

(release/25.2) rootless: fix dangling screen pixmap on RootlessUpdateScreenPixmap() OOM#3507
metux wants to merge 1 commit into
release/25.2from
pr/release/25.2-rootless-fix-dangling-screen-pixmap-on-rootlessupdatescreenpixmap-oom_2026-08-07_14-53-37

Conversation

@metux

@metux metux commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

On a calloc() failure while growing the rootless screen pixmap buffer, the
old buffer was already freed and pixmap_data_size already bumped to the new
(larger) size before the failure check -- leaving s->pixmap_data (and the
screen pixmap pPix, still pointing at the freed block via its prior
ModifyPixmapHeader() call) dangling. Worse, because pixmap_data_size was
already bumped, a later same-or-smaller-size call sees pixmap_data_size <
rowbytes as false and skips reallocating forever, permanently pinning the
dangling state instead of retrying.

Trigger: real host memory pressure during a rootless (Xquartz-style DDX)
geometry change.

Fix: allocate the replacement into a temporary first; only free the old
buffer and update pixmap_data_size/pixmap_data together once the new
allocation has succeeded.

Found via a fleet-directed alloc-fail/UAF sweep of Xext/, mi/, and miext/,
not from a live crash report. Verification note: miext/rootless/ only
compiles into hw/xquartz, which this Linux build has disabled -- checked
with a standalone gcc -fsyntax-only pass instead of the normal
ninja+meson-test build/test cycle used for the other fixes in this sweep.

Signed-off-by: Enrico Weigelt, metux IT consult info@metux.net
(cherry picked from commit d536dde)


Backport of master PR #3277 (rootless: fix dangling screen pixmap on RootlessUpdateScreenPixmap() OOM).


Backport series of master PR #3277 — same fix on every maintained release line:

This is the 25.2 copy (base release/25.2). The others are linked above.

On a calloc() failure while growing the rootless screen pixmap buffer, the
old buffer was already freed and pixmap_data_size already bumped to the new
(larger) size before the failure check -- leaving s->pixmap_data (and the
screen pixmap pPix, still pointing at the freed block via its prior
ModifyPixmapHeader() call) dangling. Worse, because pixmap_data_size was
already bumped, a later same-or-smaller-size call sees pixmap_data_size <
rowbytes as false and skips reallocating forever, permanently pinning the
dangling state instead of retrying.

Trigger: real host memory pressure during a rootless (Xquartz-style DDX)
geometry change.

Fix: allocate the replacement into a temporary first; only free the old
buffer and update pixmap_data_size/pixmap_data together once the new
allocation has succeeded.

Found via a fleet-directed alloc-fail/UAF sweep of Xext/, mi/, and miext/,
not from a live crash report. Verification note: miext/rootless/ only
compiles into hw/xquartz, which this Linux build has disabled -- checked
with a standalone `gcc -fsyntax-only` pass instead of the normal
ninja+meson-test build/test cycle used for the other fixes in this sweep.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
(cherry picked from commit d536dde)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant