Rebuild tigervnc against updated xorg-x11-server
Fixes CVE-2026-50256 CVE-2026-50257 CVE-2026-50258 CVE-2026-50259 CVE-2026-50260 CVE-2026-50261 CVE-2026-50262 CVE-2026-50263 CVE-2026-50264 Resolves: RHEL-183998
This commit is contained in:
parent
f0b7a5de2a
commit
3e7b5e494d
@ -5,7 +5,7 @@
|
||||
|
||||
Name: tigervnc
|
||||
Version: 1.15.0
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Summary: A TigerVNC remote display system
|
||||
|
||||
%global _hardened_build 1
|
||||
@ -57,17 +57,6 @@ Patch209: xorg-CVE-2025-26601.patch
|
||||
Patch210: xorg-CVE-2025-26601-2.patch
|
||||
Patch211: xorg-CVE-2025-26601-3.patch
|
||||
Patch212: xorg-CVE-2025-26601-4.patch
|
||||
# CVE-2026-33999
|
||||
Patch213: xorg-CVE-2026-33999.patch
|
||||
# CVE-2026-34000
|
||||
Patch214: xorg-CVE-2026-34000.patch
|
||||
# CVE-2026-34001
|
||||
Patch215: xorg-CVE-2026-34001.patch
|
||||
# CVE-2026-34002
|
||||
Patch216: xorg-CVE-2026-34002.patch
|
||||
# CVE-2026-34003
|
||||
Patch217: xorg-CVE-2026-34003-1.patch
|
||||
Patch218: xorg-CVE-2026-34003-2.patch
|
||||
|
||||
BuildRequires: make
|
||||
BuildRequires: gcc-c++
|
||||
@ -243,12 +232,6 @@ cat ../xserver120.patch | patch -p1
|
||||
%patch -P210 -p1 -b .xorg-CVE-2025-26601-2
|
||||
%patch -P211 -p1 -b .xorg-CVE-2025-26601-3
|
||||
%patch -P212 -p1 -b .xorg-CVE-2025-26601-4
|
||||
%patch -P213 -p1 -b .xorg-CVE-2026-33999
|
||||
%patch -P214 -p1 -b .xorg-CVE-2026-34000
|
||||
%patch -P215 -p1 -b .xorg-CVE-2026-34001
|
||||
%patch -P216 -p1 -b .xorg-CVE-2026-34002
|
||||
%patch -P217 -p1 -b .xorg-CVE-2026-34003-1
|
||||
%patch -P218 -p1 -b .xorg-CVE-2026-34003-2
|
||||
popd
|
||||
|
||||
%patch -P1 -p1 -b .use-gnome-as-default-session
|
||||
@ -417,6 +400,10 @@ fi
|
||||
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
|
||||
|
||||
%changelog
|
||||
* Wed Jun 17 2026 Jan Grulich <jgrulich@redhat.com> - 1.15.0-10
|
||||
- Rebuild for updated xorg-x11-server
|
||||
Resolves: RHEL-183998
|
||||
|
||||
* Mon Apr 20 2026 Jan Grulich <jgrulich@redhat.com> - 1.15.0-9
|
||||
- Fix CVE-2026-33999, CVE-2026-34000, CVE-2026-34001, CVE-2026-34002,
|
||||
CVE-2026-34003 xorg-x11-server: various XKB and XSYNC vulnerabilities
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
From 750205e2a8ba90ce532b19a953e8dba221e62648 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Harris <pharris2@rocketsoftware.com>
|
||||
Date: Thu, 15 Jan 2026 15:54:09 -0500
|
||||
Subject: [PATCH xserver 1/6] 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 <pharris2@rocketsoftware.com>
|
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
|
||||
(cherry picked from commit b024ae1749ee58c6fbf863b9a1f5dc440fee2e1b)
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2178>
|
||||
---
|
||||
xkb/xkb.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c
|
||||
index d5f790338..b002da5bc 100644
|
||||
--- a/xkb/xkb.c
|
||||
+++ b/xkb/xkb.c
|
||||
@@ -3003,7 +3003,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
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
From 229b7ab7ee48cf9640d635d7db7e32ce00fcb8be Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||
Date: Wed, 18 Feb 2026 16:03:11 +0100
|
||||
Subject: [PATCH xserver 2/6] 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 <ofourdan@redhat.com>
|
||||
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
|
||||
(cherry picked from commit 81b6a34f90b28c32ad499a78a4f391b7c06daea2)
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2178>
|
||||
---
|
||||
xkb/xkb.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c
|
||||
index b002da5bc..9cd2afdb8 100644
|
||||
--- a/xkb/xkb.c
|
||||
+++ b/xkb/xkb.c
|
||||
@@ -5602,7 +5602,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
|
||||
|
||||
@ -1,103 +0,0 @@
|
||||
From f6638d751790ee3f5ca672a9db303bbf5b66d020 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||
Date: Wed, 18 Feb 2026 16:23:23 +0100
|
||||
Subject: [PATCH xserver 3/6] 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 <ofourdan@redhat.com>
|
||||
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
|
||||
(cherry picked from commit f19ab94ba9c891d801231654267556dc7f32b5e0)
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2178>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
From 5842fd1fcce48ec98bdcce75b804210584ea35e2 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||
Date: Wed, 18 Feb 2026 17:02:09 +0100
|
||||
Subject: [PATCH xserver 4/6] 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 <ofourdan@redhat.com>
|
||||
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
|
||||
(cherry picked from commit f056ce1cc96ed9261052c31524162c78e458f98c)
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2178>
|
||||
---
|
||||
xkb/xkb.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c
|
||||
index 9cd2afdb8..f47ffbc5d 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;
|
||||
@@ -2567,7 +2571,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
|
||||
|
||||
@ -1,112 +0,0 @@
|
||||
From 5d6f378904ec5c7ae22e9ba4afd15e889a0a1df5 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||
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 <ofourdan@redhat.com>
|
||||
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
|
||||
(cherry picked from commit b85b00dd7b9eee05e3c12e7ad1fce4fc6671507b)
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2178>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,221 +0,0 @@
|
||||
From 7c03d504c2b6ca498e0ff3761b000d77788f0c23 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||
Date: Mon, 2 Mar 2026 14:09:57 +0100
|
||||
Subject: [PATCH xserver 6/6] 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 <ofourdan@redhat.com>
|
||||
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
|
||||
(cherry picked from commit d38c563fab5c4a554e0939da39e4d1dadef7cbae)
|
||||
|
||||
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2178>
|
||||
---
|
||||
xkb/xkb.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 55 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c
|
||||
index 1ee9cfb6f..f81d20655 100644
|
||||
--- a/xkb/xkb.c
|
||||
+++ b/xkb/xkb.c
|
||||
@@ -1752,6 +1752,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) {
|
||||
swaps(&wire->nSyms);
|
||||
}
|
||||
@@ -1790,6 +1795,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];
|
||||
}
|
||||
|
||||
@@ -1813,11 +1824,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;
|
||||
@@ -1828,6 +1840,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];
|
||||
@@ -1846,7 +1863,8 @@ CheckKeyActions(XkbDescPtr xkb,
|
||||
}
|
||||
|
||||
static int
|
||||
-CheckKeyBehaviors(XkbDescPtr xkb,
|
||||
+CheckKeyBehaviors(ClientPtr client,
|
||||
+ XkbDescPtr xkb,
|
||||
xkbSetMapReq * req,
|
||||
xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
|
||||
{
|
||||
@@ -1872,6 +1890,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;
|
||||
@@ -1897,7 +1920,8 @@ CheckKeyBehaviors(XkbDescPtr xkb,
|
||||
}
|
||||
|
||||
static int
|
||||
-CheckVirtualMods(XkbDescRec * xkb,
|
||||
+CheckVirtualMods(ClientPtr client,
|
||||
+ XkbDescRec * xkb,
|
||||
xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
|
||||
{
|
||||
register CARD8 *wire = *wireRtrn;
|
||||
@@ -1909,12 +1933,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;
|
||||
@@ -1940,6 +1970,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;
|
||||
@@ -1995,7 +2030,8 @@ CheckModifierMap(ClientPtr client, XkbDescPtr xkb, xkbSetMapReq * req,
|
||||
}
|
||||
|
||||
static int
|
||||
-CheckVirtualModMap(XkbDescPtr xkb,
|
||||
+CheckVirtualModMap(ClientPtr client,
|
||||
+ XkbDescPtr xkb,
|
||||
xkbSetMapReq * req,
|
||||
xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
|
||||
{
|
||||
@@ -2019,6 +2055,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;
|
||||
@@ -2562,7 +2603,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;
|
||||
@@ -2570,18 +2611,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;
|
||||
}
|
||||
@@ -2592,7 +2633,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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user