From 5328a544ba6c32ecdd1758283ee69058dec100f8 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Wed, 18 Feb 2026 17:02:09 +0100 Subject: [PATCH] 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 Acked-by: Peter Hutterer (cherry picked from commit f056ce1cc96ed9261052c31524162c78e458f98c) Part-of: --- xkb/xkb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xkb/xkb.c b/xkb/xkb.c index 92729d651..882dd6d59 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -1940,8 +1940,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; @@ -1965,6 +1965,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; @@ -2568,7 +2572,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; }