Bug 2545945 (CVE-2026-93524) - CVE-2026-93524 xorg-x11-server: XKB SetMap Key Width/Action Count Desync Out-Of-Bounds Read
Summary: CVE-2026-93524 xorg-x11-server: XKB SetMap Key Width/Action Count Desync Out-...
Keywords:
Status: NEW
Alias: CVE-2026-93524
Deadline: 2026-10-07
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-10-05 15:34 UTC by OSIDB Bzimport
Modified: 2026-10-07 15:51 UTC (History)
3 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-10-05 15:34:29 UTC
CheckKeySyms() in xkb/xkb.c populates a symsPerKey[] validation array with
new key widths for keys in the SetMap request range, then continues filling
entries for keys beyond the range. However, the second loop starts at index
i = nKeySyms (the first loop's counter) rather than i = firstKeySym +
nKeySyms. When firstKeySym is large and nKeySyms is small, the second loop
overwrites symsPerKey[target] with the old width from the existing map.

CheckKeyActions() then validates the wire action count against the stale old
width and accepts it. In _XkbSetMap(), SetKeySyms() widens the key (resizing
actions to nGroups * newWidth), but SetKeyActions() then resizes again to the
old count. A subsequent XkbGetMap request reads XkbKeyNumActions() entries
(derived from the new wider key_sym_map.width) from the shorter action
allocation, causing an out-of-bounds heap read. The overread bytes are
copied into the GetMap reply and sent back to the requesting client,
producing a bounded heap information disclosure.

Fixed in: xorg-server-21.1.25 and xwayland-24.1.14


* Patch
From 2d6e9cd5f0e79115e1c0573f9473a8e8fa7dd12a Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer>
Date: Thu, 3 Sep 2026 14:55:27 +1000
Subject: [PATCH xserver] xkb: fix CheckKeySyms overwriting request-range
 symsPerKey entries

CheckKeySyms() has two loops: the first processes keys in the SetMap
request range, the second fills in any missing keys from the existing
map.

The indexing between the two was inconsistent: the first loop
uses a zero-based index + req->firstKeySym, the second loop used it just
as zero-based index.

Example:
   req->firstKeySym = 50
   req->nKeySyms = 10

  i goes from 0 to 10,
  loop 1 checks [50, 60), changes the width but finishes with i at 10.
  loop 2 then runs over [10, 255(, copying the old keymap width

The second loop overwrites the new widths with the width of the
existing keymap. The subsequent SetKeySyms worked on the new width
and may write fewer actions than the map width.

A subsequent XkbGetMap request would then read XkbKeyNumActions()
entries (derived from the new wider key_sym_map.width) from the shorter
action allocation, causing an out-of-bounds heap read. The overread
bytes would be copied into the GetMap reply and sent back to the client,
producing a bounded heap information disclosure.

This vulnerability was discovered by:
  WONJOON HWANG (@joon1337) working with TrendAI Zero Day Initiative

ZDI-CAN-32408

CVE-2026-93524

Assisted-by: Claude:claude-opus-4-6
#+begin_src diff
---
 xkb/xkb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xkb/xkb.c b/xkb/xkb.c
index cbbbc5055e3c..9ed01552e12b 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -1808,16 +1808,17 @@ CheckKeySyms(ClientPtr client,
             if (!_XkbCheckRequestBounds(client, req, pSyms, &pSyms[wire->nSyms])) {
                 ,*errorRtrn = _XkbErrCode3(0x19, i + req->firstKeySym, wire->nSyms);
                 return 0;
             }
         }
         wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
     }
 
+    i = req->firstKeySym + req->nKeySyms;
     map = &xkb->map->key_sym_map[i];
     for (; i <= (unsigned) xkb->max_key_code; i++, map++) {
         register int g, nG, w;
 
         nG = XkbKeyNumGroups(xkb, i);
         for (w = g = 0; g < nG; g++) {
             if (map->kt_index[g] >= (unsigned) nTypes) {
                 ,*errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]);
-- 
2.55.0
#+end_src


Note You need to log in before you can comment on or make changes to this bug.