Bug 2545908 (CVE-2026-93520)

Summary: CVE-2026-93520 xorg-x11-server: xorg-x11-server: arbitrary code execution via out-of-bounds write in XKB keycode handling
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: rhel-process-autobot, security-response-team, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in xorg-x11-server. In the X Keyboard Extension (XKB), key name memory is allocated with an insufficient buffer size compared to the maximum supported range. An authenticated local client can exploit this flaw by sending requests that modify the keycode range, triggering a heap-based buffer overflow. This vulnerability can lead to arbitrary code execution or cause a Denial of Service (DoS) by crashing the X server.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Deadline: 2026-10-07   

Description OSIDB Bzimport 2026-10-05 13:02:52 UTC
This is caused by an incomplete fix regression from commit a3171732d.
     XkbAllocNames() still uses max_key_code+1 for the names->keys allocation
     size, while memset in the ChangeKeycodeRange path uses MAP_LENGTH which
     can be larger. This causes a heap out-of-bounds write when the keycode
     range is changed to a value where MAP_LENGTH exceeds max_key_code+1.

     An authenticated X client can trigger this by sending XKB requests that
     change the keycode range.

     The heap out-of-bounds write can lead to arbitrary code execution or denial
     of service.

     Fixed in: xorg-server-21.1.25 and xwayland-24.1.14
     Fix: https://gitlab.freedesktop.org/xorg/xserver/-/commit/TBD
     Found by: Anonymous working with TrendAI Zero Day Initiative.
               (ZDI-CAN-31941)


* Patch
From 58e2874f69ef83323cdd18a4004535e06a8947bb Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer>
Date: Wed, 26 Aug 2026 17:04:03 +1000
Subject: [PATCH xserver] xkb: allocate names->keys to MAP_LENGTH in
 XkbAllocNames

Commit a3171732d ("xkb: Always use MAP_LENGTH keymap size") converted
most XKB allocation functions to use MAP_LENGTH (256) instead of
max_key_code + 1. It also removed the per-array reallocarray() calls in
XkbChangeKeycodeRange(), replacing them with a memset up to MAP_LENGTH.
However, XkbAllocNames() was missed and still allocates names->keys to
max_key_code + 1.

When a keycodes component with max_key_code < 255 is loaded (e.g.
sun(type6) with max_key_code=132) and then a SetMap request extends
maxKeyCode to 255, XkbChangeKeycodeRange() memsets names->keys from
max_key_code to MAP_LENGTH-1, writing past the undersized allocation.

Fix by allocating names->keys to MAP_LENGTH, consistent with all other
keymap arrays after a3171732d.

This vulnerability was discovered by:
  Anonymous working with TrendAI Zero Day Initiative

ZDI-CAN-31941

CVE-2026-93520

Fixes: a3171732da50 ("xkb: Always use MAP_LENGTH keymap size")

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

diff --git a/xkb/XKBAlloc.c b/xkb/XKBAlloc.c
index dced42eebd2c..314a858ddb09 100644
--- a/xkb/XKBAlloc.c
+++ b/xkb/XKBAlloc.c
@@ -143,17 +143,17 @@ XkbAllocNames(XkbDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases)
             }
         }
     }
     if ((which & XkbKeyNamesMask) && (names->keys == NULL)) {
         if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
             (!XkbIsLegalKeycode(xkb->max_key_code)) ||
             (xkb->max_key_code < xkb->min_key_code))
             return BadValue;
-        names->keys = calloc((xkb->max_key_code + 1), sizeof(XkbKeyNameRec));
+        names->keys = calloc(MAP_LENGTH, sizeof(XkbKeyNameRec));
         if (names->keys == NULL)
             return BadAlloc;
     }
     if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) {
         if (names->key_aliases == NULL) {
             names->key_aliases = calloc(nTotalAliases, sizeof(XkbKeyAliasRec));
         }
         else if (nTotalAliases > names->num_key_aliases) {
-- 
2.55.0
#+end_src

Comment 1 Jon Orris 2026-10-19 04:00:04 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 9

Via RHSA-2026:84574 https://access.redhat.com/errata/RHSA-2026:84574

Comment 2 Jon Orris 2026-10-19 14:14:34 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 10

Via RHSA-2026:85191 https://access.redhat.com/errata/RHSA-2026:85191

Comment 3 Jon Orris 2026-10-19 14:40:45 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 9

Via RHSA-2026:85193 https://access.redhat.com/errata/RHSA-2026:85193