During extension init this makes sense, failing to assign a name to a
new device is more controversial but none of the paths handle
this situation correctly right now so we're just as likely to introduce
an exploit if the name remains NULL.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2184>
Add a new commmand line option to enable the Xwayland
clipboard selection bridge when running in rootful mode.
By default, clipboard selection bridge is disabled to keep the default
of having Xwayland rootful running isolated from the rest of the
applications.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2139>
To implement selection bridges, we need to be able to set the
SelectionOwner from the Xserver code.
Rather than duplicating the dix code for ProcSetSelectionOwner(), move
the code to its own dixSetSelectionOwner() function, and hook that from
the existing ProcSetSelectionOwner().
With that, a DDX can set the selection owner as intended.
This is preparation work for the following commits, no functional change
intended.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2139>
This is intended to be used to implement selection bridges in mixed
windowing systems such as Xwayland.
This adds a new SelectionBridgeCallback along with a new
SelectionBridgeInfoRec to convey the information from a selection
request so that a DDX such as Xwayland can bridge that to some other
clipboard implementation from another windowing system directly from the
DDX.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Assisted-by: Cursor AI
Assisted-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2139>
Commit 34934c37d6 restored calling register_damage() in
xwl_realize_window() before ensure_surface_for_window().
However if register_damage() succeeds and ensure_surface_for_window()
returns NULL, it would exit without "unregistering" the damage hook.
The X11 window, however, may still get damages reports, in which case
xwl_window_from_window() would return NULL, causing a NULL pointer
dereference in damage_report().
To avoid the issue, make sure we unregister the damage report if
ensure_surface_for_window() has failed, and add an early exit in
damage_report() if xwl_window is NULL.
v2: unregister_damage() unconditionally if ensure_surface_for_window()
failed (Michel Dänzer)
Fixes: commit 34934c37d6 ("revert: register damage before ensure_surface_for_window")
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/work_items/1886
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2190>
SProcVidModeSwitchToMode() only byte-swapped the screen field (CARD32)
from the 52-byte xXF86VidModeSwitchToModeReq struct. All other fields
were passed to ProcVidModeSwitchToMode unswapped.
This implements full swapping, including the pre-v2 version because how
could we have lived without that for so long...
SwapRestL is not technically needed but added for consistency with other
request handlers.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
The dispatch infrastructure already handles request length byte-swapping via
get_req_len() / client->req_len, so let's not double-swap the length
field back to the wrong byte order.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
Three GLX byte-swap dispatch functions advance the pc pointer past the
vendor private header (pc += __GLX_VENDPRIV_HDR_SIZE) for local field
swapping, then pass the ADVANCED pc to the non-swap handler. But the
non-swap handlers expect pc to point to the start of the
xGLXVendorPrivateReq — they cast pc to xGLXVendorPrivateReq* to access
req->contextTag, then do their own pc += __GLX_VENDPRIV_HDR_SIZE.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
SProcRenderSetPictureFilter() swapped the picture and nbytes fields but
did not swap the xFixed (CARD32) filter parameter values that follow the
filter name string in the request body.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
ProcShmCreateSegment() sent the xShmCreateSegmentReply to the client
without byte-swapping the sequenceNumber field for byte-swapped clients.
Every other SHM Proc function that sends a reply (ProcShmQueryVersion,
ProcShmGetImage) correctly swaps the reply fields.
The sequenceNumber is a CARD16 that Xlib/XCB uses to match replies to
their corresponding requests. With a garbled sequence number, the client
library will mismatch the reply with the wrong request, causing the
client to hang waiting for the real reply, process stale data from a
different request's reply, or crash due to unexpected reply format.
Fix by adding byte-swap of sequenceNumber and length before
WriteToClient, consistent with the other SHM reply handlers.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
The CARD32 *value pointer was computed as (ptr + sizeof(rep))
BEFORE the NULL check for ptr. If AddFragment returns NULL, this
performs pointer arithmetic on a null pointer, which is undefined
behavior per C11 section 6.5.6 paragraph 8. With aggressive compiler
optimizations (e.g., GCC -O2 with LTO), the compiler could reason
that since ptr was used in arithmetic, it must be non-NULL, and
optimize away the NULL check entirely. This would then cause a
write to an invalid address on OOM.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
The byte-swap check for rep.spec.client used 'client->swapped'
(the queried client) instead of 'sendClient->swapped' (the
requesting client). The reply is sent to sendClient, so swapping
must be based on sendClient's byte order. When a byte-swapped
client queries a native-byte-order client (or vice versa), the
spec.client field in the reply has the wrong byte order, causing
the client library to misinterpret the XID. Lines 504 and later
correctly use sendClient->swapped, so this was an oversight.
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
SProcXResQueryClientIds() swapped the numSpecs field but did not swap
the individual xXResClientIdSpec entries that follow the request header.
Each spec contains two CARD32 fields: client (an XID) and mask (a
bitmask selecting which client ID types to query).
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181>
Commit 0e08e5083 ("xwayland: prevent X11 get enter event when pointer is
over Wayland client") introduced a pointer crossing count to avoid
sending spurious pointer enter events when the pointer is withing a
Wayland native surface.
However, that change breaks tablet devices, as the pointer enter count
is only updated from the wl_pointer enter/leave events, a slave X11
device such as a tablet pointer would report a lost focus and the event
wrongly sent to the root window.
To avoid the issue, revert partially commit 0e08e5083 to return FALSE
as before for the slave devices. The rest of the logic from commit
0e08e5083 remains unchanged, so that we do not send spurious
XCrossingEvents for the pointer device when it's within a native Wayland
surface.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/work_items/1884
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2180>
newPix leaks if AddResource() call failes inside the FOR_NSCREENS
loop (per-screen pixmap IDs).
free newPix in mentioned execution path to prevent potential leak.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Signed-off-by: Mikhail Dmitrichenko <m.dmitrichenko222@gmail.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2173>
len calculation and strncpy limit were off by one when prefixing
"vmod_" to the virtual modifier name. This could write the final
NULL one byte past the allocated buffer from tbGetBuffer().
Use proper allocation len for prefix to avoid writing out-of-bounds.
Found by Linux Verification Center (linuxtesting.org) with SVACE
Signed-off-by: Mikhail Dmitrichenko <m.dmitrichenko222@gmail.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2175>
The window name buffer after XWDFileHeader is fixed at
XWD_WINDOW_NAME_LEN (60 bytes). sprintf could overflow when
hostname is close to maximum length and combined with the
prefix "Xvfb " + display + screen number.
Switch to snprintf to guarantee we never write beyond the
allocated buffer.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Signed-off-by: Mikhail Dmitrichenko <m.dmitrichenko222@gmail.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2172>
In XkbAddGeomDoodad(), when adding a doodad to a specific section
(section != NULL), there is a comparison between section->num_doodads
and geom->sz_doodads instead of the section's own section->sz_doodads.
The else branch (global geometry doodads) was already correct.
Compare section->num_doodads against section->sz_doodads to prevent
a potential out-of-bounds.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Signed-off-by: Mikhail Dmitrichenko <m.dmitrichenko222@gmail.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2174>
Similar to the recent fixes, add more _XkbCheckRequestBounds() to the
functions that loop over the request data, i.e.:
* CheckKeySyms()
* CheckKeyActions()
* CheckKeyBehaviors()
* CheckVirtualMods()
* CheckKeyExplicit()
* CheckVirtualModMap()
* _XkbSetMapChecks()
All these are static functions so we can add the client to the parameters
without breaking any API.
See also:
CVE-2026-34003, ZDI-CAN-28736, CVE-2026-34002, ZDI-CAN-28737
v2: Check for "nSyms != 0" in CheckKeySyms() to avoid false positives.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2176>
The function CheckKeyTypes() will loop over the client's request but
won't perform any additional bound checking to ensure that the data
read remains within the request bounds.
As a result, a specifically crafted request may cause CheckKeyTypes() to
read past the request data, as reported by valgrind:
== Invalid read of size 2
== at 0x5A3D1D: CheckKeyTypes (xkb.c:1694)
== by 0x5A6A9C: _XkbSetMapChecks (xkb.c:2515)
== by 0x5A759E: ProcXkbSetMap (xkb.c:2736)
== by 0x5BF832: SProcXkbSetMap (xkbSwap.c:245)
== by 0x5C05ED: SProcXkbDispatch (xkbSwap.c:501)
== by 0x4A20DF: Dispatch (dispatch.c:551)
== by 0x4B03B4: dix_main (main.c:277)
== by 0x428941: main (stubmain.c:34)
== Address is 30 bytes after a block of size 28,672 in arena "client"
==
== Invalid read of size 2
== at 0x5A3AB6: CheckKeyTypes (xkb.c:1669)
== by 0x5A6A9C: _XkbSetMapChecks (xkb.c:2515)
== by 0x5A759E: ProcXkbSetMap (xkb.c:2736)
== by 0x5BF832: SProcXkbSetMap (xkbSwap.c:245)
== by 0x5C05ED: SProcXkbDispatch (xkbSwap.c:501)
== by 0x4A20DF: Dispatch (dispatch.c:551)
== by 0x4B03B4: dix_main (main.c:277)
== by 0x428941: main (stubmain.c:34)
== Address is 2 bytes after a block of size 28,672 alloc'd
== at 0x4848897: realloc (vg_replace_malloc.c:1804)
== by 0x5E357A: ReadRequestFromClient (io.c:336)
== by 0x4A1FAB: Dispatch (dispatch.c:519)
== by 0x4B03B4: dix_main (main.c:277)
== by 0x428941: main (stubmain.c:34)
==
== Invalid write of size 2
== at 0x5A3AD7: CheckKeyTypes (xkb.c:1669)
== by 0x5A6A9C: _XkbSetMapChecks (xkb.c:2515)
== by 0x5A759E: ProcXkbSetMap (xkb.c:2736)
== by 0x5BF832: SProcXkbSetMap (xkbSwap.c:245)
== by 0x5C05ED: SProcXkbDispatch (xkbSwap.c:501)
== by 0x4A20DF: Dispatch (dispatch.c:551)
== by 0x4B03B4: dix_main (main.c:277)
== by 0x428941: main (stubmain.c:34)
== Address is 2 bytes after a block of size 28,672 alloc'd
== at 0x4848897: realloc (vg_replace_malloc.c:1804)
== by 0x5E357A: ReadRequestFromClient (io.c:336)
== by 0x4A1FAB: Dispatch (dispatch.c:519)
== by 0x4B03B4: dix_main (main.c:277)
== by 0x428941: main (stubmain.c:34)
==
To avoid that issue, add additional bounds checking within the loops by
calling _XkbCheckRequestBounds() and report an error if we are to read
past the client's request.
CVE-2026-34003, ZDI-CAN-28736
This vulnerability was discovered by:
Jan-Niklas Sohn working with TrendAI Zero Day Initiative
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2176>
As reported by valgrind:
== Conditional jump or move depends on uninitialised value(s)
== at 0x547E5B: CheckModifierMap (xkb.c:1972)
== by 0x54A086: _XkbSetMapChecks (xkb.c:2574)
== by 0x54A845: ProcXkbSetMap (xkb.c:2741)
== by 0x556EF4: ProcXkbDispatch (xkb.c:7048)
== by 0x454A8C: Dispatch (dispatch.c:553)
== by 0x462CEB: dix_main (main.c:274)
== by 0x405EA7: main (stubmain.c:34)
== Uninitialised value was created by a heap allocation
== at 0x4840B26: malloc (vg_replace_malloc.c:447)
== by 0x592D5A: AllocateInputBuffer (io.c:981)
== by 0x591F77: InsertFakeRequest (io.c:516)
== by 0x45CA27: NextAvailableClient (dispatch.c:3629)
== by 0x58FA81: AllocNewConnection (connection.c:628)
== by 0x58FC70: EstablishNewConnections (connection.c:692)
== by 0x58FFAA: HandleNotifyFd (connection.c:809)
== by 0x593F42: ospoll_wait (ospoll.c:660)
== by 0x58B9B6: WaitForSomething (WaitFor.c:208)
== by 0x4548AC: Dispatch (dispatch.c:493)
== by 0x462CEB: dix_main (main.c:274)
== by 0x405EA7: main (stubmain.c:34)
The issue is that the loop in CheckModifierMap() reads from wire without
verifying that the data is within the request bounds.
The req->totalModMapKeys value could exceed the actual data provided,
causing reads of uninitialized memory.
To fix that issue, we add a bounds check using _XkbCheckRequestBounds,
but for that, we need to also pass a ClientPtr parameter, which is not
a problem since CheckModifierMap() is a private, static function.
CVE-2026-34002, ZDI-CAN-28737
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2176>
As reported by valgrind:
== Invalid read of size 8
== at 0x568C14: miSyncTriggerFence (misync.c:140)
== by 0x540688: ProcSyncTriggerFence (sync.c:1957)
== by 0x540CCC: ProcSyncDispatch (sync.c:2152)
== by 0x4A28C5: Dispatch (dispatch.c:553)
== by 0x4B0B24: dix_main (main.c:274)
== by 0x42915E: main (stubmain.c:34)
== Address 0x17e35488 is 8 bytes inside a block of size 16 free'd
== at 0x4843E43: free (vg_replace_malloc.c:990)
== by 0x53D683: SyncDeleteTriggerFromSyncObject (sync.c:169)
== by 0x53F14D: FreeAwait (sync.c:1208)
== by 0x4DFB06: doFreeResource (resource.c:888)
== by 0x4DFC59: FreeResource (resource.c:918)
== by 0x53E349: SyncAwaitTriggerFired (sync.c:701)
== by 0x568C52: miSyncTriggerFence (misync.c:142)
== by 0x540688: ProcSyncTriggerFence (sync.c:1957)
== by 0x540CCC: ProcSyncDispatch (sync.c:2152)
== by 0x4A28C5: Dispatch (dispatch.c:553)
== by 0x4B0B24: dix_main (main.c:274)
== by 0x42915E: main (stubmain.c:34)
== Block was alloc'd at
== at 0x4840B26: malloc (vg_replace_malloc.c:447)
== by 0x5E50E1: XNFalloc (utils.c:1129)
== by 0x53D772: SyncAddTriggerToSyncObject (sync.c:206)
== by 0x53DCA8: SyncInitTrigger (sync.c:414)
== by 0x5409C7: ProcSyncAwaitFence (sync.c:2089)
== by 0x540D04: ProcSyncDispatch (sync.c:2160)
== by 0x4A28C5: Dispatch (dispatch.c:553)
== by 0x4B0B24: dix_main (main.c:274)
== by 0x42915E: main (stubmain.c:34)
When walking the list of fences to trigger, miSyncTriggerFence() may
call TriggerFence() for the current trigger, which end up calling the
function SyncAwaitTriggerFired().
SyncAwaitTriggerFired() frees the entire await resource, which removes
all triggers from that await - including pNext which may be another
trigger from the same await attached to the same fence.
On the next iteration, ptl = pNext points to freed memory...
To avoid the issue, we need to restart the iteration from the beginning
of the list each time a trigger fires, since the callback can modify the
list.
CVE-2026-34001, ZDI-CAN-28706
This vulnerability was discovered by:
Jan-Niklas Sohn working with TrendAI Zero Day Initiative
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2176>
As reported by valgrind:
== Conditional jump or move depends on uninitialised value(s)
== at 0x5CBE66: SrvXkbAddGeomKeyAlias (XKBGAlloc.c:585)
== by 0x5AC7D5: _CheckSetGeom (xkb.c:5607)
== by 0x5AC952: _XkbSetGeometry (xkb.c:5643)
== by 0x5ACB58: ProcXkbSetGeometry (xkb.c:5684)
== by 0x5B0DAC: ProcXkbDispatch (xkb.c:7070)
== by 0x4A28C5: Dispatch (dispatch.c:553)
== by 0x4B0B24: dix_main (main.c:274)
== by 0x42915E: main (stubmain.c:34)
== Uninitialised value was created by a heap allocation
== at 0x4840B26: malloc (vg_replace_malloc.c:447)
== by 0x5E13B0: AllocateInputBuffer (io.c:981)
== by 0x5E05CD: InsertFakeRequest (io.c:516)
== by 0x4AA860: NextAvailableClient (dispatch.c:3629)
== by 0x5DE0D7: AllocNewConnection (connection.c:628)
== by 0x5DE2C6: EstablishNewConnections (connection.c:692)
== by 0x5DE600: HandleNotifyFd (connection.c:809)
== by 0x5E2598: ospoll_wait (ospoll.c:660)
== by 0x5DA00C: WaitForSomething (WaitFor.c:208)
== by 0x4A26E5: Dispatch (dispatch.c:493)
== by 0x4B0B24: dix_main (main.c:274)
== by 0x42915E: main (stubmain.c:34)
Each key alias entry contains two key names (the alias and the real key
name), each of size XkbKeyNameLength.
The current bounds check only validates the first name, allowing
XkbAddGeomKeyAlias to potentially read uninitialized memory when
accessing the second name at &wire[XkbKeyNameLength].
To fix this, change the value to check to use 2 * XkbKeyNameLength to
validate the bounds.
CVE-2026-34000, ZDI-CAN-28679
This vulnerability was discovered by:
Jan-Niklas Sohn working with TrendAI Zero Day Initiative
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2176>
If the "compat" buffer has previously been truncated, there will be
unused space in the buffer. The code uses this space, but does not
update the number of valid entries in the buffer.
In the best case, this leads to the new compat entries being ignored. In the
worst case, if there are any "skipped" compat entries, the number of
valid entries will be corrupted, potentially leading to a buffer read
overrun when processing a future request.
Set the number of used "compat" entries when re-using previously
allocated space in the buffer.
CVE-2026-33999, ZDI-CAN-28593
This vulnerability was discovered by:
Jan-Niklas Sohn working with TrendAI Zero Day Initiative
Signed-off-by: Peter Harris <pharris2@rocketsoftware.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2176>
Reported in #1817:
xwayland-24.1.6/redhat-linux-build/../xkb/xkbInit.c:527:5:
warning[-Wanalyzer-malloc-leak]: leak of ‘rmlvo_dflts.layout’
xwayland-24.1.6/redhat-linux-build/../xkb/xkbInit.c:527:5:
warning[-Wanalyzer-malloc-leak]: leak of ‘rmlvo_dflts.model’
xwayland-24.1.6/redhat-linux-build/../xkb/xkbInit.c:527:5:
warning[-Wanalyzer-malloc-leak]: leak of ‘rmlvo_dflts.options’
xwayland-24.1.6/redhat-linux-build/../xkb/xkbInit.c:527:5:
warning[-Wanalyzer-malloc-leak]: leak of ‘rmlvo_dflts.rules’
xwayland-24.1.6/redhat-linux-build/../xkb/xkbInit.c:527:5:
warning[-Wanalyzer-malloc-leak]: leak of ‘rmlvo_dflts.variant’
Fixes: 56a5955c8 ("xkb: strdup the values returned by XkbGetRulesDflts")
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2169>