From 5d6f378904ec5c7ae22e9ba4afd15e889a0a1df5 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Mon, 23 Feb 2026 15:52:49 +0100 Subject: [PATCH xserver 5/6] 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 Acked-by: Peter Hutterer (cherry picked from commit b85b00dd7b9eee05e3c12e7ad1fce4fc6671507b) Part-of: --- xkb/xkb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/xkb/xkb.c b/xkb/xkb.c index f47ffbc5d..1ee9cfb6f 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -1639,6 +1639,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) { swaps(&wire->virtualMods); } @@ -1664,7 +1668,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) { swaps(&mapWire[n].virtualMods); -- 2.53.0