Your message dated Sat, 16 May 2026 11:07:43 +0000
with message-id <[email protected]>
and subject line Released with 12.14
has caused the Debian Bug report #1134331,
regarding bookworm-pu: package xorg-server/2:21.1.7-3+deb12u12
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1134331: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1134331
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm d-i
X-Debbugs-Cc: [email protected], [email protected], 
[email protected], [email protected], [email protected], [email protected], 
[email protected], [email protected]
Control: affects -1 + src:xorg-server
User: [email protected]
Usertags: pu

Hi

Same as for #1134330: xorg-server is affected by some CVEs recently disclosed 
but we
discussed in the team that they do not warrant a DSA, so proposing
those to be fixed via the next trixie point release:

  * xkb: fix buffer re-use in _XkbSetCompatMap (CVE-2026-33999)
  * xkb: Fix bounds check in _CheckSetGeom() (CVE-2026-34000)
  * miext/sync: Fix use-after-free in miSyncTriggerFence() (CVE-2026-34001)
  * xkb: Fix out-of-bounds read in CheckModifierMap() (CVE-2026-34002)
  * xkb: Add additional bound checking in CheckKeyTypes() (CVE-2026-34003)
  * xkb: Add more _XkbCheckRequestBounds() (CVE-2026-34003)

They are already fixed in unstable and exposed there, afaik there are
no regressions reported. Currently debusine tests are still running,
which I'm using to augment confidence:
https://debusine.debian.net/debian/developers/work-request/611326/

Regards,
Salvatore
diff -u xorg-server-21.1.7/debian/changelog xorg-server-21.1.7/debian/changelog
--- xorg-server-21.1.7/debian/changelog
+++ xorg-server-21.1.7/debian/changelog
@@ -1,3 +1,15 @@
+xorg-server (2:21.1.7-3+deb12u12) bookworm; urgency=medium
+
+  * Non-maintainer upload.
+  * xkb: fix buffer re-use in _XkbSetCompatMap (CVE-2026-33999)
+  * xkb: Fix bounds check in _CheckSetGeom() (CVE-2026-34000)
+  * miext/sync: Fix use-after-free in miSyncTriggerFence() (CVE-2026-34001)
+  * xkb: Fix out-of-bounds read in CheckModifierMap() (CVE-2026-34002)
+  * xkb: Add additional bound checking in CheckKeyTypes() (CVE-2026-34003)
+  * xkb: Add more _XkbCheckRequestBounds() (CVE-2026-34003)
+
+ -- Salvatore Bonaccorso <[email protected]>  Sat, 11 Apr 2026 02:48:00 +0200
+
 xorg-server (2:21.1.7-3+deb12u11) bookworm-security; urgency=high
 
   * Non-maintainer upload by the Security Team.
diff -u xorg-server-21.1.7/debian/patches/series 
xorg-server-21.1.7/debian/patches/series
--- xorg-server-21.1.7/debian/patches/series
+++ xorg-server-21.1.7/debian/patches/series
@@ -49,3 +49,9 @@
 CVE-2025-62230/0001-xkb-Make-the-RT_XKBCLIENT-resource-private.patch
 CVE-2025-62230/0002-xkb-Free-the-XKB-resource-when-freeing-XkbInterest.patch
 CVE-2025-62231/0001-xkb-Prevent-overflow-in-XkbSetCompatMap.patch
+CVE-2026-33999/0001-xkb-fix-buffer-re-use-in-_XkbSetCompatMap.patch
+CVE-2026-34000/0001-xkb-Fix-bounds-check-in-_CheckSetGeom.patch
+CVE-2026-34001/0001-miext-sync-Fix-use-after-free-in-miSyncTriggerFence.patch
+CVE-2026-34002/0001-xkb-Fix-out-of-bounds-read-in-CheckModifierMap.patch
+CVE-2026-34003/0001-xkb-Add-additional-bound-checking-in-CheckKeyTypes.patch
+CVE-2026-34003/0002-xkb-Add-more-_XkbCheckRequestBounds.patch
only in patch2:
unchanged:
--- 
xorg-server-21.1.7.orig/debian/patches/CVE-2026-33999/0001-xkb-fix-buffer-re-use-in-_XkbSetCompatMap.patch
+++ 
xorg-server-21.1.7/debian/patches/CVE-2026-33999/0001-xkb-fix-buffer-re-use-in-_XkbSetCompatMap.patch
@@ -0,0 +1,44 @@
+From d4a18e229af79917d09b2a24f38df95374c536e2 Mon Sep 17 00:00:00 2001
+From: Peter Harris <[email protected]>
+Date: Thu, 15 Jan 2026 15:54:09 -0500
+Subject: [PATCH xserver] xkb: fix buffer re-use in _XkbSetCompatMap
+
+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 <[email protected]>
+Acked-by: Olivier Fourdan <[email protected]>
+---
+ xkb/xkb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/xkb/xkb.c b/xkb/xkb.c
+index c4ed3fb1e..d31c64113 100644
+--- a/xkb/xkb.c
++++ b/xkb/xkb.c
+@@ -3008,7 +3008,7 @@ _XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
+                 return BadAlloc;
+             }
+         }
+-        else if (req->truncateSI) {
++        else if (req->truncateSI || req->firstSI + req->nSI > compat->num_si) 
{
+             compat->num_si = req->firstSI + req->nSI;
+         }
+         sym = &compat->sym_interpret[req->firstSI];
+-- 
+2.53.0
+
only in patch2:
unchanged:
--- 
xorg-server-21.1.7.orig/debian/patches/CVE-2026-34000/0001-xkb-Fix-bounds-check-in-_CheckSetGeom.patch
+++ 
xorg-server-21.1.7/debian/patches/CVE-2026-34000/0001-xkb-Fix-bounds-check-in-_CheckSetGeom.patch
@@ -0,0 +1,67 @@
+From b81454f29d7e408d682ef1371ae1df63871cd7ed Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <[email protected]>
+Date: Wed, 18 Feb 2026 16:03:11 +0100
+Subject: [PATCH xserver] xkb: Fix bounds check in _CheckSetGeom()
+
+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 <[email protected]>
+Acked-by: Peter Hutterer <[email protected]>
+---
+ xkb/xkb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/xkb/xkb.c b/xkb/xkb.c
+index d31c64113..d2b15b485 100644
+--- a/xkb/xkb.c
++++ b/xkb/xkb.c
+@@ -5613,7 +5613,7 @@ _CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * 
req, ClientPtr client)
+     }
+ 
+     for (i = 0; i < req->nKeyAliases; i++) {
+-        if (!_XkbCheckRequestBounds(client, req, wire, wire + 
XkbKeyNameLength))
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 2 * 
XkbKeyNameLength))
+                 return BadLength;
+ 
+         if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
+-- 
+2.53.0
+
only in patch2:
unchanged:
--- 
xorg-server-21.1.7.orig/debian/patches/CVE-2026-34001/0001-miext-sync-Fix-use-after-free-in-miSyncTriggerFence.patch
+++ 
xorg-server-21.1.7/debian/patches/CVE-2026-34001/0001-miext-sync-Fix-use-after-free-in-miSyncTriggerFence.patch
@@ -0,0 +1,100 @@
+From e684fb34a858191769ff1c064bd4ab40f6ff7189 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <[email protected]>
+Date: Wed, 18 Feb 2026 16:23:23 +0100
+Subject: [PATCH xserver] miext/sync: Fix use-after-free in
+ miSyncTriggerFence()
+
+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 <[email protected]>
+Acked-by: Peter Hutterer <[email protected]>
+---
+ miext/sync/misync.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/miext/sync/misync.c b/miext/sync/misync.c
+index 0931803f6..9a6fbbd4a 100644
+--- a/miext/sync/misync.c
++++ b/miext/sync/misync.c
+@@ -131,16 +131,22 @@ miSyncDestroyFence(SyncFence * pFence)
+ void
+ miSyncTriggerFence(SyncFence * pFence)
+ {
+-    SyncTriggerList *ptl, *pNext;
++    SyncTriggerList *ptl;
++    Bool triggered;
+ 
+     pFence->funcs.SetTriggered(pFence);
+ 
+     /* run through triggers to see if any fired */
+-    for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) {
+-        pNext = ptl->next;
+-        if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, 0))
+-            (*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
+-    }
++    do {
++        triggered = FALSE;
++        for (ptl = pFence->sync.pTriglist; ptl; ptl = ptl->next) {
++            if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, 0)) {
++                (*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
++                triggered = TRUE;
++                break;
++            }
++        }
++    } while (triggered);
+ }
+ 
+ SyncScreenFuncsPtr
+-- 
+2.53.0
+
only in patch2:
unchanged:
--- 
xorg-server-21.1.7.orig/debian/patches/CVE-2026-34002/0001-xkb-Fix-out-of-bounds-read-in-CheckModifierMap.patch
+++ 
xorg-server-21.1.7/debian/patches/CVE-2026-34002/0001-xkb-Fix-out-of-bounds-read-in-CheckModifierMap.patch
@@ -0,0 +1,88 @@
+From 822657b357048ddedfb4e8313c7f1a69295240c5 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <[email protected]>
+Date: Wed, 18 Feb 2026 17:02:09 +0100
+Subject: [PATCH xserver] xkb: Fix out-of-bounds read in CheckModifierMap()
+
+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 <[email protected]>
+Acked-by: Peter Hutterer <[email protected]>
+---
+ xkb/xkb.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/xkb/xkb.c b/xkb/xkb.c
+index d2b15b485..b03d6a264 100644
+--- a/xkb/xkb.c
++++ b/xkb/xkb.c
+@@ -1944,8 +1944,8 @@ CheckKeyExplicit(XkbDescPtr xkb,
+ }
+ 
+ static int
+-CheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn,
+-                 int *errRtrn)
++CheckModifierMap(ClientPtr client, XkbDescPtr xkb, xkbSetMapReq * req,
++                 CARD8 **wireRtrn, int *errRtrn)
+ {
+     register CARD8 *wire = *wireRtrn;
+     CARD8 *start;
+@@ -1969,6 +1969,10 @@ CheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, 
CARD8 **wireRtrn,
+     }
+     start = wire;
+     for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 2)) {
++            *errRtrn = _XkbErrCode3(0x64, req->totalModMapKeys, i);
++            return 0;
++        }
+         if ((wire[0] < first) || (wire[0] > last)) {
+             *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]);
+             return 0;
+@@ -2571,7 +2575,7 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, 
xkbSetMapReq * req,
+         return BadValue;
+     }
+     if ((req->present & XkbModifierMapMask) &&
+-        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
++        (!CheckModifierMap(client, xkb, req, (CARD8 **) &values, &error))) {
+         client->errorValue = error;
+         return BadValue;
+     }
+-- 
+2.53.0
+
only in patch2:
unchanged:
--- 
xorg-server-21.1.7.orig/debian/patches/CVE-2026-34003/0001-xkb-Add-additional-bound-checking-in-CheckKeyTypes.patch
+++ 
xorg-server-21.1.7/debian/patches/CVE-2026-34003/0001-xkb-Add-additional-bound-checking-in-CheckKeyTypes.patch
@@ -0,0 +1,109 @@
+From d41409dfc193d1a2ca84f19ad59b2b84de68c3e0 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <[email protected]>
+Date: Mon, 23 Feb 2026 15:52:49 +0100
+Subject: [PATCH xserver 1/2] xkb: Add additional bound checking in
+ CheckKeyTypes()
+
+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 <[email protected]>
+Acked-by: Peter Hutterer <[email protected]>
+---
+ xkb/xkb.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/xkb/xkb.c b/xkb/xkb.c
+index b03d6a264..a90845230 100644
+--- a/xkb/xkb.c
++++ b/xkb/xkb.c
+@@ -1643,6 +1643,10 @@ CheckKeyTypes(ClientPtr client,
+     for (i = 0; i < req->nTypes; i++) {
+         unsigned width;
+ 
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
++            *nMapsRtrn = _XkbErrCode3(0x0b, req->nTypes, i);
++            return 0;
++        }
+         if (client->swapped && doswap) {
+             swaps(&wire->virtualMods);
+         }
+@@ -1668,7 +1672,18 @@ CheckKeyTypes(ClientPtr client,
+             xkbModsWireDesc *preWire;
+ 
+             mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
++            if (!_XkbCheckRequestBounds(client, req, mapWire,
++                                        &mapWire[wire->nMapEntries])) {
++                *nMapsRtrn = _XkbErrCode3(0x0c, i, wire->nMapEntries);
++                return 0;
++            }
+             preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
++            if (wire->preserve &&
++                !_XkbCheckRequestBounds(client, req, preWire,
++                                        &preWire[wire->nMapEntries])) {
++                *nMapsRtrn = _XkbErrCode3(0x0d, i, wire->nMapEntries);
++                return 0;
++            }
+             for (n = 0; n < wire->nMapEntries; n++) {
+                 if (client->swapped && doswap) {
+                     swaps(&mapWire[n].virtualMods);
+-- 
+2.53.0
+
only in patch2:
unchanged:
--- 
xorg-server-21.1.7.orig/debian/patches/CVE-2026-34003/0002-xkb-Add-more-_XkbCheckRequestBounds.patch
+++ 
xorg-server-21.1.7/debian/patches/CVE-2026-34003/0002-xkb-Add-more-_XkbCheckRequestBounds.patch
@@ -0,0 +1,218 @@
+From a44b3d0bc1b80beeac50f5b52fb3f4cc07e77f64 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <[email protected]>
+Date: Mon, 2 Mar 2026 14:09:57 +0100
+Subject: [PATCH xserver 2/2] xkb: Add more _XkbCheckRequestBounds()
+
+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 <[email protected]>
+Acked-by: Peter Hutterer <[email protected]>
+---
+ xkb/xkb.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 55 insertions(+), 14 deletions(-)
+
+diff --git a/xkb/xkb.c b/xkb/xkb.c
+index a90845230..652996946 100644
+--- a/xkb/xkb.c
++++ b/xkb/xkb.c
+@@ -1756,6 +1756,11 @@ CheckKeySyms(ClientPtr client,
+         KeySym *pSyms;
+         register unsigned nG;
+ 
++        /* Check we received enough data to read the next xkbSymMapWireDesc */
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
++            *errorRtrn = _XkbErrCode3(0x18, i + req->firstKeySym, i);
++            return 0;
++        }
+         if (client->swapped && doswap) {
+             swaps(&wire->nSyms);
+         }
+@@ -1794,6 +1799,12 @@ CheckKeySyms(ClientPtr client,
+             return 0;
+         }
+         pSyms = (KeySym *) &wire[1];
++        if (wire->nSyms != 0) {
++            if (!_XkbCheckRequestBounds(client, req, pSyms, 
&pSyms[wire->nSyms])) {
++                *errorRtrn = _XkbErrCode3(0x19, i + req->firstKeySym, 
wire->nSyms);
++                return 0;
++            }
++        }
+         wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
+     }
+ 
+@@ -1817,11 +1828,12 @@ CheckKeySyms(ClientPtr client,
+ }
+ 
+ static int
+-CheckKeyActions(XkbDescPtr xkb,
+-                xkbSetMapReq * req,
+-                int nTypes,
+-                CARD8 *mapWidths,
+-                CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
++CheckKeyActions(ClientPtr client,
++               XkbDescPtr xkb,
++               xkbSetMapReq * req,
++               int nTypes,
++               CARD8 *mapWidths,
++               CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
+ {
+     int nActs;
+     CARD8 *wire = *wireRtrn;
+@@ -1832,6 +1844,11 @@ CheckKeyActions(XkbDescPtr xkb,
+     CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, 
(*nActsRtrn),
+                        0);
+     for (nActs = i = 0; i < req->nKeyActs; i++) {
++        /* Check we received enough data to read the next byte on the wire */
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
++            *nActsRtrn = _XkbErrCode3(0x24, i + req->firstKeyAct, i);
++            return 0;
++        }
+         if (wire[0] != 0) {
+             if (wire[0] == symsPerKey[i + req->firstKeyAct])
+                 nActs += wire[0];
+@@ -1850,7 +1867,8 @@ CheckKeyActions(XkbDescPtr xkb,
+ }
+ 
+ static int
+-CheckKeyBehaviors(XkbDescPtr xkb,
++CheckKeyBehaviors(ClientPtr client,
++                  XkbDescPtr xkb,
+                   xkbSetMapReq * req,
+                   xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
+ {
+@@ -1876,6 +1894,11 @@ CheckKeyBehaviors(XkbDescPtr xkb,
+     }
+ 
+     for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
++        /* Check we received enough data to read the next behavior */
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
++            *errorRtrn = _XkbErrCode3(0x36, first, i);
++            return 0;
++        }
+         if ((wire->key < first) || (wire->key > last)) {
+             *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
+             return 0;
+@@ -1901,7 +1924,8 @@ CheckKeyBehaviors(XkbDescPtr xkb,
+ }
+ 
+ static int
+-CheckVirtualMods(XkbDescRec * xkb,
++CheckVirtualMods(ClientPtr client,
++                 XkbDescRec * xkb,
+                  xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
+ {
+     register CARD8 *wire = *wireRtrn;
+@@ -1913,12 +1937,18 @@ CheckVirtualMods(XkbDescRec * xkb,
+         if (req->virtualMods & bit)
+             nMods++;
+     }
++    /* Check we received enough data for the number of virtual mods expected 
*/
++    if (!_XkbCheckRequestBounds(client, req, wire, wire + 
XkbPaddedSize(nMods))) {
++        *errorRtrn = _XkbErrCode3(0x37, nMods, i);
++        return 0;
++    }
+     *wireRtrn = (wire + XkbPaddedSize(nMods));
+     return 1;
+ }
+ 
+ static int
+-CheckKeyExplicit(XkbDescPtr xkb,
++CheckKeyExplicit(ClientPtr client,
++                 XkbDescPtr xkb,
+                  xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
+ {
+     register CARD8 *wire = *wireRtrn;
+@@ -1944,6 +1974,11 @@ CheckKeyExplicit(XkbDescPtr xkb,
+     }
+     start = wire;
+     for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
++        /* Check we received enough data to read the next two bytes */
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 2)) {
++            *errorRtrn = _XkbErrCode4(0x54, first, last, i);
++            return 0;
++        }
+         if ((wire[0] < first) || (wire[0] > last)) {
+             *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
+             return 0;
+@@ -1999,7 +2034,8 @@ CheckModifierMap(ClientPtr client, XkbDescPtr xkb, 
xkbSetMapReq * req,
+ }
+ 
+ static int
+-CheckVirtualModMap(XkbDescPtr xkb,
++CheckVirtualModMap(ClientPtr client,
++                   XkbDescPtr xkb,
+                    xkbSetMapReq * req,
+                    xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
+ {
+@@ -2023,6 +2059,11 @@ CheckVirtualModMap(XkbDescPtr xkb,
+         return 0;
+     }
+     for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
++        /* Check we received enough data to read the next virtual mod map key 
*/
++        if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
++            *errRtrn = _XkbErrCode3(0x74, first, i);
++            return 0;
++        }
+         if ((wire->key < first) || (wire->key > last)) {
+             *errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
+             return 0;
+@@ -2566,7 +2607,7 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, 
xkbSetMapReq * req,
+     }
+ 
+     if ((req->present & XkbKeyActionsMask) &&
+-        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
++        (!CheckKeyActions(client, xkb, req, nTypes, mapWidths, symsPerKey,
+                           (CARD8 **) &values, &nActions))) {
+         client->errorValue = nActions;
+         return BadValue;
+@@ -2574,18 +2615,18 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, 
xkbSetMapReq * req,
+ 
+     if ((req->present & XkbKeyBehaviorsMask) &&
+         (!CheckKeyBehaviors
+-         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
++         (client, xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
+         client->errorValue = error;
+         return BadValue;
+     }
+ 
+     if ((req->present & XkbVirtualModsMask) &&
+-        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
++        (!CheckVirtualMods(client, xkb, req, (CARD8 **) &values, &error))) {
+         client->errorValue = error;
+         return BadValue;
+     }
+     if ((req->present & XkbExplicitComponentsMask) &&
+-        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
++        (!CheckKeyExplicit(client, xkb, req, (CARD8 **) &values, &error))) {
+         client->errorValue = error;
+         return BadValue;
+     }
+@@ -2596,7 +2637,7 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, 
xkbSetMapReq * req,
+     }
+     if ((req->present & XkbVirtualModMapMask) &&
+         (!CheckVirtualModMap
+-         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
++         (client, xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
+         client->errorValue = error;
+         return BadValue;
+     }
+-- 
+2.53.0
+

--- End Message ---
--- Begin Message ---
Package: release.debian.org
Version: 12.14

This update has been released as part of Debian 12.14.

--- End Message ---

Reply via email to