已合并
fix 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 #402
fix 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 #402
已合并
ultra_planet创建于 6月8日
10 个文件变更+901-1
@@ -0,0 +1,112 @@
1+From 4926348d826b7dc12d51d7e41bd9068aee5f90af Mon Sep 17 00:00:00 2001
2+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
3+Date: Wed, 13 May 2026 14:29:26 +0200
4+Subject: [PATCH] dri2: Use booleans for (fake) front buffer tracking in
5+ do_get_buffers
6+MIME-Version: 1.0
7+Content-Type: text/plain; charset=UTF-8
8+Content-Transfer-Encoding: 8bit
9+ 
10+This works as intended — the (fake) front buffer needs to be added
11+only if the client didn't request it in the first place — even if the
12+client requests the same attachment multiple times. This ensures we
13+never try to access more than (count + 1) entries of the buffers array.
14+ 
15+Fixes: ff6c7764c290 ("DRI2: Implement protocol for DRI2GetBuffersWithFormat")
16+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
17+(cherry picked from commit b7aa65cc3bb11b792ce2a3f511ba9b863acb11c8)
18+ 
19+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
20+ 
21+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/4926348d826b7dc12d51d7e41bd9068aee5f90af
22+Conflict:no
23+---
24+ hw/xfree86/dri2/dri2.c | 37 ++++++++++++++++++-------------------
25+ 1 file changed, 18 insertions(+), 19 deletions(-)
26+ 
27+diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
28+index 3975d40ca..5c251cc5a 100644
29+--- a/hw/xfree86/dri2/dri2.c
30++++ b/hw/xfree86/dri2/dri2.c
31+@@ -563,9 +563,10 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
32+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
33+ DRI2ScreenPtr ds;
34+ DRI2BufferPtr *buffers;
35+- int need_real_front = 0;
36+- int need_fake_front = 0;
37+- int have_fake_front = 0;
38++ Bool need_real_front = FALSE;
39++ Bool have_real_front = FALSE;
40++ Bool need_fake_front = FALSE;
41++ Bool have_fake_front = FALSE;
42+ int front_format = 0;
43+ int dimensions_match;
44+ int buffers_changed = 0;
45+@@ -598,34 +599,32 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
46+ if (buffers[i] == NULL)
47+ goto err_out;
48+
49+- /* If the drawable is a window and the front-buffer is requested,
50+- * silently add the fake front-buffer to the list of requested
51+- * attachments. The counting logic in the loop accounts for the case
52+- * where the client requests both the fake and real front-buffer.
53++ /* In certain cases the (fake) front buffer is always needed, so return
54++ * it even if the client failed to request it.
55++ * The logic in & after the loop accounts for the case where the client
56++ * does request the (fake) front buffer, to avoid returning it multiple
57++ * times.
58+ */
59+ if (attachment == DRI2BufferBackLeft) {
60+- need_real_front++;
61++ need_real_front = TRUE;
62+ front_format = format;
63+ }
64+
65+ if (attachment == DRI2BufferFrontLeft) {
66+- need_real_front--;
67++ have_real_front = TRUE;
68+ front_format = format;
69+
70+- if (pDraw->type == DRAWABLE_WINDOW) {
71+- need_fake_front++;
72+- }
73++ if (pDraw->type == DRAWABLE_WINDOW)
74++ need_fake_front = TRUE;
75+ }
76+
77+ if (pDraw->type == DRAWABLE_WINDOW) {
78+- if (attachment == DRI2BufferFakeFrontLeft) {
79+- need_fake_front--;
80+- have_fake_front = 1;
81+- }
82++ if (attachment == DRI2BufferFakeFrontLeft)
83++ have_fake_front = TRUE;
84+ }
85+ }
86+
87+- if (need_real_front > 0) {
88++ if (need_real_front && !have_real_front) {
89+ if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft,
90+ front_format, dimensions_match,
91+ &buffers[i]))
92+@@ -636,7 +635,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
93+ i++;
94+ }
95+
96+- if (need_fake_front > 0) {
97++ if (need_fake_front && !have_fake_front) {
98+ if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft,
99+ front_format, dimensions_match,
100+ &buffers[i]))
101+@@ -646,7 +645,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
102+ goto err_out;
103+
104+ i++;
105+- have_fake_front = 1;
106++ have_fake_front = TRUE;
107+ }
108+
109+ *out_count = i;
110+--
111+2.33.0
112+ 
@@ -0,0 +1,143 @@
1+From f0b8e6e1d969548c0625051d56a780e5df39de26 Mon Sep 17 00:00:00 2001
2+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
3+Date: Fri, 15 May 2026 17:47:51 +0200
4+Subject: [PATCH] dri2: Deduplicate attachments in do_get_buffer
5+MIME-Version: 1.0
6+Content-Type: text/plain; charset=UTF-8
7+Content-Transfer-Encoding: 8bit
8+ 
9+It was always the intention of the DRI2 protocol that there's at most
10+one instance of each attachment, and that's how it was implemented in
11+Mesa.
12+ 
13+Since that wasn't enforced though, there might be other clients in the
14+wild which (e.g. accidentally) request the same attachment multiple
15+times. So starting to a raise a protocol error in this case now risks
16+breaking such clients.
17+ 
18+Instead, just deduplicate the attachments using a bit-set.
19+ 
20+This has a couple of desirable side effects:
21+ 
22+* destroy_buffer cannot be called multiple times for the same
23+ DRI2BufferPtr.
24+* The client cannot cause the server to allocate a buffers array with
25+ more entries than there are attachments (currently 11).
26+ 
27+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
28+(cherry picked from commit 339c279514326134b0878fc23ce6e9520440ce7f)
29+ 
30+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
31+ 
32+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/f0b8e6e1d969548c0625051d56a780e5df39de26
33+Conflict:no
34+---
35+ hw/xfree86/dri2/dri2.c | 36 ++++++++++++++++++++++--------------
36+ 1 file changed, 22 insertions(+), 14 deletions(-)
37+ 
38+diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
39+index 5c251cc5a..bf62538c5 100644
40+--- a/hw/xfree86/dri2/dri2.c
41++++ b/hw/xfree86/dri2/dri2.c
42+@@ -563,16 +563,16 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
43+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
44+ DRI2ScreenPtr ds;
45+ DRI2BufferPtr *buffers;
46++ unsigned attachments_bitset = 0;
47+ Bool need_real_front = FALSE;
48+- Bool have_real_front = FALSE;
49+ Bool need_fake_front = FALSE;
50+- Bool have_fake_front = FALSE;
51+ int front_format = 0;
52+ int dimensions_match;
53+ int buffers_changed = 0;
54+ int i;
55+
56+- if (!pPriv) {
57++ if (!pPriv ||
58++ count > DRI2BufferHiz + 1) {
59+ *width = pDraw->width;
60+ *height = pDraw->height;
61+ *out_count = 0;
62+@@ -584,7 +584,10 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
63+ dimensions_match = (pDraw->width == pPriv->width)
64+ && (pDraw->height == pPriv->height);
65+
66+- buffers = calloc((count + 1), sizeof(buffers[0]));
67++ /* Since we deduplicate attachments in the buffers array, there cannot be
68++ * more entries than there are attachments.
69++ */
70++ buffers = calloc((min(count, DRI2BufferHiz) + 1), sizeof(buffers[0]));
71+ if (!buffers)
72+ goto err_out;
73+
74+@@ -592,6 +595,14 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
75+ const unsigned attachment = *(attachments++);
76+ const unsigned format = (has_format) ? *(attachments++) : 0;
77+
78++ if (attachment > DRI2BufferHiz)
79++ goto err_out;
80++
81++ if (attachments_bitset & (1u << attachment))
82++ continue;
83++
84++ attachments_bitset |= 1u << attachment;
85++
86+ if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
87+ format, dimensions_match, &buffers[i]))
88+ buffers_changed = 1;
89+@@ -611,20 +622,15 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
90+ }
91+
92+ if (attachment == DRI2BufferFrontLeft) {
93+- have_real_front = TRUE;
94+ front_format = format;
95+
96+ if (pDraw->type == DRAWABLE_WINDOW)
97+ need_fake_front = TRUE;
98+ }
99+-
100+- if (pDraw->type == DRAWABLE_WINDOW) {
101+- if (attachment == DRI2BufferFakeFrontLeft)
102+- have_fake_front = TRUE;
103+- }
104+ }
105+
106+- if (need_real_front && !have_real_front) {
107++ if (need_real_front &&
108++ !(attachments_bitset & (1u << DRI2BufferFrontLeft))) {
109+ if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft,
110+ front_format, dimensions_match,
111+ &buffers[i]))
112+@@ -635,7 +641,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
113+ i++;
114+ }
115+
116+- if (need_fake_front && !have_fake_front) {
117++ if (need_fake_front &&
118++ !(attachments_bitset & (1u << DRI2BufferFakeFrontLeft))) {
119+ if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft,
120+ front_format, dimensions_match,
121+ &buffers[i]))
122+@@ -645,7 +652,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
123+ goto err_out;
124+
125+ i++;
126+- have_fake_front = TRUE;
127++ attachments_bitset |= 1u << DRI2BufferFakeFrontLeft;
128+ }
129+
130+ *out_count = i;
131+@@ -657,7 +664,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
132+ * contents of the real front-buffer. This ensures correct operation of
133+ * applications that call glXWaitX before calling glDrawBuffer.
134+ */
135+- if (have_fake_front && buffers_changed) {
136++ if (buffers_changed &&
137++ (attachments_bitset & (1u << DRI2BufferFakeFrontLeft))) {
138+ BoxRec box;
139+ RegionRec region;
140+
141+--
142+2.33.0
143+ 
@@ -0,0 +1,93 @@
1+From a569eb4f36ed96a9e445ececd7e8d98c223461a0 Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Wed, 29 Apr 2026 05:40:33 +0000
4+Subject: [PATCH] dix: increase XLFDMAXFONTNAMELEN to match libXfont2's
5+ MAXFONTNAMELEN
6+ 
7+XLFDMAXFONTNAMELEN was 256 bytes, but libXfont2 defines MAXFONTNAMELEN
8+as 1024 and allows font names and alias targets up to that length in
9+fonts.alias files.
10+ 
11+doListFontsAndAliases copies the resolved alias target into a
12+stack-allocated tmp_pattern[XLFDMAXFONTNAMELEN] and then into
13+c->current.pattern[XLFDMAXFONTNAMELEN] (defined in LFWIstateRec).
14+doListFontsWithInfo has the same pattern, copying the resolved name into
15+c->current.pattern[]. With the old 256-byte limit, a fonts.alias entry
16+with a target name between 257 and 1023 bytes would overflow both
17+buffers.
18+ 
19+An attacker can exploit this by:
20+ 1. Creating a font directory with a fonts.alias containing an alias
21+ whose target name exceeds 256 bytes
22+ 2. Using SetFontPath to add the malicious directory
23+ 3. Calling ListFonts with the alias name to trigger alias resolution
24+ 4. The oversized resolved name overflows the 256-byte stack buffer
25+ 
26+Increase XLFDMAXFONTNAMELEN from 256 to 1024 to match libXfont2's
27+MAXFONTNAMELEN, ensuring the server can handle any name the font library
28+produces.
29+ 
30+This vulnerability was discovered by:
31+Anonymous working with TrendAI Zero Day Initiative
32+ 
33+ZDI-CAN-30136
34+ 
35+Assisted-by: Claude:claude-opus-4-6
36+(cherry picked from commit bb5158f962dc935e58ef8b4b5fcb31be201a6e07)
37+ 
38+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
39+ 
40+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/a569eb4f36ed96a9e445ececd7e8d98c223461a0
41+Conflict:Adapt context
42+---
43+ dix/dixfonts.c | 8 ++++++++
44+ include/closestr.h | 7 ++++++-
45+ 2 files changed, 14 insertions(+), 1 deletion(-)
46+ 
47+diff --git a/dix/dixfonts.c b/dix/dixfonts.c
48+index 0ea8678..386c386 100644
49+--- a/dix/dixfonts.c
50++++ b/dix/dixfonts.c
51+@@ -671,6 +671,10 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
52+ * is BadFontName, indicating the alias resolution
53+ * is complete.
54+ */
55++ if (resolvedlen > XLFDMAXFONTNAMELEN) {
56++ err = BadFontName;
57++ goto ContBadFontName;
58++ }
59+ memmove(tmp_pattern, resolved, resolvedlen);
60+ if (c->haveSaved) {
61+ char *tmpname;
62+@@ -934,6 +938,10 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
63+ memmove(c->savedName, name, namelen + 1);
64+ aliascount = 20;
65+ }
66++ if (namelen > XLFDMAXFONTNAMELEN) {
67++ err = BadFontName;
68++ goto ContBadFontName;
69++ }
70+ memmove(c->current.pattern, name, namelen);
71+ c->current.patlen = namelen;
72+ c->current.max_names = 1;
73+diff --git a/include/closestr.h b/include/closestr.h
74+index 60e6f09..7567ac6 100644
75+--- a/include/closestr.h
76++++ b/include/closestr.h
77+@@ -57,7 +57,12 @@ typedef struct _OFclosure {
78+
79+ /* ListFontsWithInfo */
80+
81+-#define XLFDMAXFONTNAMELEN 256
82++/* libXfont2 allows font names/aliases up to MAXFONTNAMELEN (1024) bytes in
83++ * fonts.alias files. The server's pattern buffers must be large enough to
84++ * hold resolved alias targets returned by the font library.
85++ * ZDI-CAN-30136
86++ */
87++#define XLFDMAXFONTNAMELEN 1024
88+ typedef struct _LFWIstate {
89+ char pattern[XLFDMAXFONTNAMELEN];
90+ int patlen;
91+--
92+2.33.0
93+ 
@@ -0,0 +1,125 @@
1+From f304b57444be3991fd9d3389f309c6eeb056a6c4 Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Mon, 20 Apr 2026 11:16:13 +1000
4+Subject: [PATCH] sync: fix deletion of counters and fences
5+ 
6+Both FreeCounter() and miSyncDestroyFence() iterate over the trigger list
7+and invoke the CounterDestroyed callback on each trigger.
8+ 
9+The CounterDestroyed callback (e.g. SyncAwaitTriggerFired) may call
10+FreeResource/FreeAwait, which frees the SyncAwaitUnion containing all
11+SyncAwait structs in the same Await group.
12+ 
13+When multiple conditions in a single Await reference the same sync
14+object (counter or fence), the first callback frees all SyncAwait
15+structs while subsequent trigger list nodes still reference them. On the
16+next iteration, reading ptl->next or ptl->pTrigger dereferences freed
17+memory, leading to a use-after-free.
18+ 
19+We need separate fixes for separate issues here to fix this in one go
20+- use our null-terminated list macro to make sure our next pointer stays
21+ valid (the code accessed ptl->next after freeing it)
22+- update the list head before deleting the trigger, eventually this ends
23+ up being NULL anyway but meanwhile the list head is a valid list
24+ during CounterDestroyed
25+- check if we actually do have a trigger before dereferencing the
26+ callback
27+- Set all triggers to NULL if they are shared so we don't dereference
28+ potentially freed memory
29+ 
30+This vulnerability was discovered by:
31+Anonymous working with TrendAI Zero Day Initiative
32+ 
33+ZDI-CAN-30159 (miSyncDestroyFence), ZDI-CAN-30163 (FreeCounter)
34+ 
35+Assisted-by: Claude:claude-opus-4-6
36+(cherry picked from commit f5abfb61994471023d8c6470428c8e30c411cc0b)
37+ 
38+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
39+ 
40+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/f304b57444be3991fd9d3389f309c6eeb056a6c4
41+Conflict:no
42+---
43+ Xext/sync.c | 32 +++++++++++++++++++++++++-------
44+ miext/sync/misync.c | 12 ++++++++----
45+ 2 files changed, 33 insertions(+), 11 deletions(-)
46+ 
47+diff --git a/Xext/sync.c b/Xext/sync.c
48+index 900858773..f4f1036d1 100644
49+--- a/Xext/sync.c
50++++ b/Xext/sync.c
51+@@ -1162,9 +1162,12 @@ FreeCounter(void *env, XID id)
52+ SyncTriggerList *ptl, *pnext;
53+
54+ /* tell all the counter's triggers that counter has been destroyed */
55+- for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
56+- (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
57+- pnext = ptl->next;
58++ nt_list_for_each_entry_safe(ptl, pnext, pCounter->sync.pTriglist, next) {
59++ /* Remove it from the list first so CounterDestroyed
60++ * callbacks have a valid list to iterate */
61++ pCounter->sync.pTriglist = pnext;
62++ if (ptl->pTrigger)
63++ (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
64+ free(ptl); /* destroy the trigger list as we go */
65+ }
66+ if (IsSystemCounter(pCounter)) {
67+@@ -1196,13 +1199,28 @@ FreeAwait(void *addr, XID id)
68+
69+ for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
70+ numwaits--, pAwait++) {
71+- /* If the counter is being destroyed, FreeCounter will delete
72+- * the trigger list itself, so don't do it here.
73++ /* If the counter is being destroyed, FreeCounter/miSyncDestroyFence
74++ * will delete the trigger list itself, so don't do it here.
75++ * However, we must NULL out the pTrigger pointer in the trigger list
76++ * node so the destroy loop knows not to dereference it - the backing
77++ * SyncAwait memory is about to be freed below.
78+ */
79+ SyncObject *pSync = pAwait->trigger.pSync;
80+
81+- if (pSync && !pSync->beingDestroyed)
82+- SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
83++ if (pSync) {
84++ if (!pSync->beingDestroyed) {
85++ SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
86++ } else {
87++ SyncTriggerList *ptl;
88++
89++ nt_list_for_each_entry(ptl, pSync->pTriglist, next) {
90++ if (ptl->pTrigger == &pAwait->trigger) {
91++ ptl->pTrigger = NULL;
92++ break;
93++ }
94++ }
95++ }
96++ }
97+ }
98+ free(pAwaitUnion);
99+ return Success;
100+diff --git a/miext/sync/misync.c b/miext/sync/misync.c
101+index 9a6fbbd4a..4ce249850 100644
102+--- a/miext/sync/misync.c
103++++ b/miext/sync/misync.c
104+@@ -115,10 +115,14 @@ miSyncDestroyFence(SyncFence * pFence)
105+ SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
106+ SyncTriggerList *ptl, *pNext;
107+
108+- /* tell all the fence's triggers that the counter has been destroyed */
109+- for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) {
110+- (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
111+- pNext = ptl->next;
112++ /* tell all the fence's triggers that the fence has been destroyed.
113++ * Update pTriglist before each callback and free so that FreeAwait
114++ * sees a valid list head when scanning for triggers to NULL out.
115++ */
116++ nt_list_for_each_entry_safe(ptl, pNext, pFence->sync.pTriglist, next) {
117++ pFence->sync.pTriglist = pNext;
118++ if (ptl->pTrigger)
119++ (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
120+ free(ptl); /* destroy the trigger list as we go */
121+ }
122+
123+--
124+2.33.0
125+ 
@@ -0,0 +1,53 @@
1+From eced7e74cad4a46c3a3c17b2df13b70b8bedfc25 Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Mon, 20 Apr 2026 11:17:41 +1000
4+Subject: [PATCH] xkb: reject key types with num_levels exceeding
5+ XkbMaxShiftLevel
6+ 
7+CheckKeyTypes validates incoming key type definitions from XkbSetMap
8+requests but does not enforce an upper bound on numLevels. A client can set
9+numLevels up to 255 on a non-canonical key type, which is stored in the
10+server's type table.
11+ 
12+When ChangeKeyboardMapping later triggers XkbUpdateKeyTypesFromCore, the
13+function XkbKeyTypesForCoreSymbols computes groupsWidth from num_levels and
14+uses the XKB_OFFSET(g, l) = (g * groupsWidth) + l macro to index into
15+tsyms[], a stack-allocated buffer of XkbMaxSymsPerKey (252) entries. With
16+num_levels=255, groupsWidth=255, and indices reach up to 3*255+254 = 1019,
17+overflowing the 252-element stack buffer by 767 KeySym-sized entries.
18+ 
19+Fix by rejecting numLevels values greater than XkbMaxShiftLevel (63) in
20+CheckKeyTypes, alongside the existing lower-bound check for numLevels < 1.
21+ 
22+This vulnerability was discovered by:
23+Anonymous working with TrendAI Zero Day Initiative
24+ 
25+ZDI-CAN-30160
26+ 
27+Assisted-by: Claude:claude-opus-4-6
28+(cherry picked from commit 543e108516428fc8c3bea91d6563ad266f9a801e)
29+ 
30+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
31+ 
32+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/eced7e74cad4a46c3a3c17b2df13b70b8bedfc25
33+Conflict:no
34+---
35+ xkb/xkb.c | 2 +-
36+ 1 file changed, 1 insertion(+), 1 deletion(-)
37+ 
38+diff --git a/xkb/xkb.c b/xkb/xkb.c
39+index d0d1b77cb..2b5027104 100644
40+--- a/xkb/xkb.c
41++++ b/xkb/xkb.c
42+@@ -1648,7 +1648,7 @@ CheckKeyTypes(ClientPtr client,
43+ }
44+ n = i + req->firstType;
45+ width = wire->numLevels;
46+- if (width < 1) {
47++ if (width < 1 || width > XkbMaxShiftLevel) {
48+ *nMapsRtrn = _XkbErrCode3(0x04, n, width);
49+ return 0;
50+ }
51+--
52+2.33.0
53+ 
@@ -0,0 +1,55 @@
1+From 54c3d9fad0f2f97835da9d275b53255f4963029f Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Mon, 20 Apr 2026 11:18:13 +1000
4+Subject: [PATCH] xkb: clamp nMaps to mapWidths buffer size in CheckKeyTypes
5+ 
6+CheckKeyTypes computes nMaps = firstType + nTypes from client-controlled
7+request fields when XkbSetMapResizeTypes is set. This value is used to
8+index mapWidths[], a stack-allocated CARD8 array of XkbMaxLegalKeyCode + 1
9+(256) elements. No upper bound is enforced on nMaps.
10+ 
11+An attacker can first send SetMap(firstType=0, nTypes=255, ResizeTypes) to
12+set the server's num_types to 255, then send SetMap(firstType=255,
13+nTypes=10, ResizeTypes). The firstType > num_types check passes because
14+255 > 255 is false (the check uses > rather than >=). nMaps is then
15+computed as 265, and the loop writes mapWidths[255..264], overflowing 9
16+bytes past the stack buffer into adjacent stack variables (symsPerKey[]).
17+ 
18+Fix by rejecting requests where firstType + nTypes would exceed the
19+mapWidths buffer size (XkbMaxLegalKeyCode + 1).
20+ 
21+This vulnerability was discovered by:
22+Anonymous working with TrendAI Zero Day Initiative
23+ 
24+ZDI-CAN-30161
25+ 
26+Assisted-by: Claude:claude-opus-4-6
27+(cherry picked from commit 867b59b33bee669cb412f1314e47c52eacf6e00b)
28+ 
29+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
30+ 
31+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/54c3d9fad0f2f97835da9d275b53255f4963029f
32+Conflict:no
33+---
34+ xkb/xkb.c | 5 +++++
35+ 1 file changed, 5 insertions(+)
36+ 
37+diff --git a/xkb/xkb.c b/xkb/xkb.c
38+index 2b5027104..fad39f9a9 100644
39+--- a/xkb/xkb.c
40++++ b/xkb/xkb.c
41+@@ -1617,6 +1617,11 @@ CheckKeyTypes(ClientPtr client,
42+ *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
43+ return 0;
44+ }
45++ if (nMaps > XkbMaxLegalKeyCode + 1) {
46++ *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes,
47++ XkbMaxLegalKeyCode + 1);
48++ return 0;
49++ }
50+ }
51+ else if (req->present & XkbKeyTypesMask) {
52+ nMaps = xkb->map->num_types;
53+--
54+2.33.0
55+ 
@@ -0,0 +1,74 @@
1+From 92a167ab3fda0bee41cf97f6a40a4c01c67d85d4 Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Mon, 20 Apr 2026 11:17:08 +1000
4+Subject: [PATCH] sync: restart trigger list iteration in SyncChangeCounter
5+ after TriggerFired
6+ 
7+This is the equivalent check to miSyncTriggerFence() from
8+commit f19ab94ba9c8 ("miext/sync: Fix use-after-free in miSyncTriggerFence()")
9+ 
10+When a trigger fires via SyncAwaitTriggerFired, the resulting
11+FreeResource/FreeAwait call invokes SyncDeleteTriggerFromSyncObject for
12+every trigger in the same Await group. This unlinks and frees the
13+corresponding trigger list nodes - potentially including the node pnext
14+points to.
15+ 
16+Fix by restarting iteration from the list head after a trigger fires, since
17+TriggerFired may have arbitrarily mutated the list. Triggers that have fired
18+are removed from the list by FreeAwait, so restarting cannot cause infinite
19+loops.
20+ 
21+This vulnerability was discovered by:
22+Anonymous working with TrendAI Zero Day Initiative
23+ 
24+ZDI-CAN-30164
25+ 
26+Assisted-by: Claude:claude-opus-4-6
27+(cherry picked from commit bdd7bf57af208b1ddf57d4683d67104443b44812)
28+ 
29+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
30+ 
31+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/92a167ab3fda0bee41cf97f6a40a4c01c67d85d4
32+Conflict:no
33+---
34+ Xext/sync.c | 23 ++++++++++++++++++++++-
35+ 1 file changed, 22 insertions(+), 1 deletion(-)
36+ 
37+diff --git a/Xext/sync.c b/Xext/sync.c
38+index f4f1036d1..0e70dd08a 100644
39+--- a/Xext/sync.c
40++++ b/Xext/sync.c
41+@@ -720,8 +720,29 @@ SyncChangeCounter(SyncCounter * pCounter, int64_t newval)
42+ /* run through triggers to see if any become true */
43+ for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
44+ pnext = ptl->next;
45+- if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval))
46++ if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval)) {
47+ (*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
48++ /* TriggerFired may have called SyncDeleteTriggerFromSyncObject
49++ * for sibling triggers in the same Await group, freeing their
50++ * trigger list nodes - potentially including pnext. Verify
51++ * pnext is still on the counter's trigger list; if not,
52++ * restart from the list head.
53++ *
54++ * Unlike miSyncTriggerFence() we cannot use a do/while
55++ * restart loop here: counter trigger lists may contain alarm
56++ * triggers which are not removed after firing and would cause
57++ * an infinite loop when delta is 0.
58++ */
59++ if (pnext) {
60++ SyncTriggerList *tmp;
61++ for (tmp = pCounter->sync.pTriglist; tmp; tmp = tmp->next) {
62++ if (tmp == pnext)
63++ break;
64++ }
65++ if (!tmp)
66++ pnext = pCounter->sync.pTriglist;
67++ }
68++ }
69+ }
70+
71+ if (IsSystemCounter(pCounter)) {
72+--
73+2.33.0
74+ 
@@ -0,0 +1,156 @@
1+From 94341bd715d62ba8da4c1851f517018996da1af8 Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Mon, 20 Apr 2026 11:18:48 +1000
4+Subject: [PATCH] glx: fix reversed length check in ChangeDrawableAttributes
5+ 
6+The request length validation in __glXDisp_ChangeDrawableAttributes and
7+__glXDispSwap_ChangeDrawableAttributes uses the wrong comparison direction.
8+The check tests whether the computed request size is LESS THAN
9+client->req_len, but should test whether it is GREATER THAN. With the
10+reversed operator, an undersized request (where numAttribs claims more
11+attribute pairs than the request actually contains) passes validation.
12+ 
13+DoChangeDrawableAttributes then iterates numAttribs attribute pairs starting
14+from the end of the request header, reading past the actual request data
15+into adjacent memory. This is an out-of-bounds read that can also cause
16+an out-of-bounds write when a GLX_EVENT_MASK attribute key is found in the
17+overread data and its corresponding value is written to pGlxDraw->eventMask.
18+ 
19+This patch effectively reverts commit 402b329c3aa8 ("glx: Work around
20+wrong request lengths sent by mesa"). This was fixed in mesa commit
21+4324d6fdfbba1 in 2011 (mesa 7.11).
22+ 
23+Fixes: 402b329c3aa8 ("glx: Work around wrong request lengths sent by mesa")
24+ 
25+This vulnerability was discovered by:
26+Anonymous working with TrendAI Zero Day Initiative
27+ 
28+ZDI-CAN-30165
29+ 
30+Assisted-by: Claude:claude-opus-4-6
31+(cherry picked from commit 6d459e4daf715bea8abdafa8fb130be2f8a1d145)
32+ 
33+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
34+ 
35+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/94341bd715d62ba8da4c1851f517018996da1af8
36+Conflict:no
37+---
38+ glx/glxcmds.c | 21 +++++----------------
39+ glx/glxcmdsswap.c | 12 +++++-------
40+ 2 files changed, 10 insertions(+), 23 deletions(-)
41+ 
42+diff --git a/glx/glxcmds.c b/glx/glxcmds.c
43+index 1e46d0c72..8a13e34b5 100644
44+--- a/glx/glxcmds.c
45++++ b/glx/glxcmds.c
46+@@ -1144,8 +1144,7 @@ __glXDisp_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc)
47+ ClientPtr client = cl->client;
48+ xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
49+
50+- /* work around mesa bug, don't use REQUEST_SIZE_MATCH */
51+- REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
52++ REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq);
53+ return DoGetFBConfigs(cl, req->screen);
54+ }
55+
56+@@ -1366,9 +1365,7 @@ __glXDisp_DestroyPixmap(__GLXclientState * cl, GLbyte * pc)
57+ ClientPtr client = cl->client;
58+ xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
59+
60+- /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
61+- * length to 3 instead of 2 */
62+- REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
63++ REQUEST_SIZE_MATCH(xGLXDestroyPixmapReq);
64+
65+ return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
66+ }
67+@@ -1524,14 +1521,8 @@ __glXDisp_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
68+ client->errorValue = req->numAttribs;
69+ return BadValue;
70+ }
71+-#if 0
72+- /* mesa sends an additional 8 bytes */
73++
74+ REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
75+-#else
76+- if (((sizeof(xGLXChangeDrawableAttributesReq) +
77+- (req->numAttribs << 3)) >> 2) < client->req_len)
78+- return BadLength;
79+-#endif
80+
81+ return DoChangeDrawableAttributes(cl->client, req->drawable,
82+ req->numAttribs, (CARD32 *) (req + 1));
83+@@ -1598,8 +1589,7 @@ __glXDisp_DestroyWindow(__GLXclientState * cl, GLbyte * pc)
84+ ClientPtr client = cl->client;
85+ xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
86+
87+- /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
88+- REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
89++ REQUEST_SIZE_MATCH(xGLXDestroyWindowReq);
90+
91+ return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
92+ }
93+@@ -1960,8 +1950,7 @@ __glXDisp_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
94+ ClientPtr client = cl->client;
95+ xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *) pc;
96+
97+- /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
98+- REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
99++ REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq);
100+
101+ return DoGetDrawableAttributes(cl, req->drawable);
102+ }
103+diff --git a/glx/glxcmdsswap.c b/glx/glxcmdsswap.c
104+index 7d6674470..96382672a 100644
105+--- a/glx/glxcmdsswap.c
106++++ b/glx/glxcmdsswap.c
107+@@ -235,7 +235,7 @@ __glXDispSwap_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc)
108+
109+ __GLX_DECLARE_SWAP_VARIABLES;
110+
111+- REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
112++ REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq);
113+
114+ __GLX_SWAP_INT(&req->screen);
115+ return __glXDisp_GetFBConfigsSGIX(cl, pc);
116+@@ -327,7 +327,7 @@ __glXDispSwap_DestroyPixmap(__GLXclientState * cl, GLbyte * pc)
117+
118+ __GLX_DECLARE_SWAP_VARIABLES;
119+
120+- REQUEST_AT_LEAST_SIZE(xGLXDestroyGLXPixmapReq);
121++ REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
122+
123+ __GLX_SWAP_SHORT(&req->length);
124+ __GLX_SWAP_INT(&req->glxpixmap);
125+@@ -440,9 +440,7 @@ __glXDispSwap_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
126+ client->errorValue = req->numAttribs;
127+ return BadValue;
128+ }
129+- if (((sizeof(xGLXChangeDrawableAttributesReq) +
130+- (req->numAttribs << 3)) >> 2) < client->req_len)
131+- return BadLength;
132++ REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
133+
134+ attribs = (CARD32 *) (req + 1);
135+ __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs << 1);
136+@@ -514,7 +512,7 @@ __glXDispSwap_DestroyWindow(__GLXclientState * cl, GLbyte * pc)
137+
138+ __GLX_DECLARE_SWAP_VARIABLES;
139+
140+- REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
141++ REQUEST_SIZE_MATCH(xGLXDestroyWindowReq);
142+
143+ __GLX_SWAP_INT(&req->glxwindow);
144+
145+@@ -723,7 +721,7 @@ __glXDispSwap_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
146+
147+ __GLX_DECLARE_SWAP_VARIABLES;
148+
149+- REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
150++ REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq);
151+
152+ __GLX_SWAP_SHORT(&req->length);
153+ __GLX_SWAP_INT(&req->drawable);
154+--
155+2.33.0
156+ 
@@ -0,0 +1,77 @@
1+From 182c23f780402062ab31963776a19d5b87e25ac8 Mon Sep 17 00:00:00 2001
2+From: Peter Hutterer <peter.hutterer@who-t.net>
3+Date: Mon, 20 Apr 2026 11:19:20 +1000
4+Subject: [PATCH] saver: re-fetch screen private after CheckScreenPrivate in
5+ CreateSaverWindow
6+MIME-Version: 1.0
7+Content-Type: text/plain; charset=UTF-8
8+Content-Transfer-Encoding: 8bit
9+ 
10+CreateSaverWindow stores pPriv (the ScreenSaverScreenPrivatePtr) in a local
11+variable via the SetupScreen macro at function entry. When an existing saver
12+window is being replaced, the function sets pPriv->hasWindow = FALSE and
13+calls CheckScreenPrivate(). If at this point pPriv->attr is NULL (cleared
14+by a prior UnsetAttributes call), pPriv->events is NULL, and
15+pPriv->installedMap is None, then CheckScreenPrivate determines the screen
16+private is unused, frees it, and sets the screen private pointer to NULL.
17+ 
18+The function then continues to dereference the now-freed pPriv on the very
19+next line (pPriv->attr), resulting in a use-after-free. On glibc 2.34+,
20+the tcache key at offset 8 within the freed block makes pPriv->attr appear
21+non-NULL, causing the function to continue operating on garbage data and
22+eventually crash.
23+ 
24+The attack sequence is:
25+ 1. SetAttributes (creates pPriv with pPriv->attr set)
26+ 2. ForceScreenSaver(Active) (creates saver window, pPriv->hasWindow=TRUE)
27+ 3. UnsetAttributes (sets pPriv->attr = NULL)
28+ 4. ForceScreenSaver(Active) (re-enters CreateSaverWindow → UAF)
29+ 
30+Fix by re-fetching pPriv from the screen private after CheckScreenPrivate
31+returns, so the subsequent NULL check correctly detects the freed state.
32+ 
33+ScreenSaverFreeAttr has the same pattern, force pPriv to NULL there too
34+even though it has no real effect.
35+ 
36+This vulnerability was discovered by:
37+Anonymous working with TrendAI Zero Day Initiative
38+ 
39+ZDI-CAN-30168
40+ 
41+Assisted-by: Claude:claude-opus-4-6
42+(cherry picked from commit ecc634f1b2f7aa473d3a267eada98c4918bf9e05)
43+ 
44+Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2229>
45+ 
46+Reference:https://gitlab.freedesktop.org/xorg/xserver/-/commit/182c23f780402062ab31963776a19d5b87e25ac8
47+Conflict:no
48+---
49+ Xext/saver.c | 5 +++++
50+ 1 file changed, 5 insertions(+)
51+ 
52+diff --git a/Xext/saver.c b/Xext/saver.c
53+index fd6153c31..0780e80ab 100644
54+--- a/Xext/saver.c
55++++ b/Xext/saver.c
56+@@ -348,6 +348,9 @@ ScreenSaverFreeAttr(void *value, XID id)
57+ dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
58+ }
59+ CheckScreenPrivate(pScreen);
60++ /* CheckScreenPrivate may have freed pPriv (same pattern as
61++ * CreateSaverWindow fix for ZDI-CAN-30168). */
62++ pPriv = NULL;
63+ return TRUE;
64+ }
65+
66+@@ -479,6 +482,8 @@ CreateSaverWindow(ScreenPtr pScreen)
67+ UninstallSaverColormap(pScreen);
68+ pPriv->hasWindow = FALSE;
69+ CheckScreenPrivate(pScreen);
70++ /* Re-fetch pPriv since CheckScreenPrivate may have freed it */
71++ pPriv = GetScreenPrivate(pScreen);
72+ }
73+ }
74+
75+--
76+2.33.0
77+ 
@@ -16,7 +16,7 @@
16 16 
17Name: xorg-x11-server17Name: xorg-x11-server
18Version: 1.20.818Version: 1.20.8
19-Release: 3719+Release: 38
20Summary: X.Org X11 X server20Summary: X.Org X11 X server
21License: MIT and GPLv221License: MIT and GPLv2
22URL: https://www.x.org22URL: https://www.x.org
@@ -160,6 +160,15 @@ Patch6072: backport-CVE-2026-34001.patch
160Patch6073: backport-CVE-2026-34002.patch160Patch6073: backport-CVE-2026-34002.patch
161Patch6074: backport-0001-CVE-2026-34003.patch161Patch6074: backport-0001-CVE-2026-34003.patch
162Patch6075: backport-0002-CVE-2026-34003.patch162Patch6075: backport-0002-CVE-2026-34003.patch
163+Patch6076: backport-CVE-2026-50256.patch
164+Patch6077: backport-CVE-2026-50257-CVE-2026-50260.patch
165+Patch6078: backport-CVE-2026-50258.patch
166+Patch6079: backport-CVE-2026-50259.patch
167+Patch6080: backport-CVE-2026-50261.patch
168+Patch6081: backport-CVE-2026-50262.patch
169+Patch6082: backport-CVE-2026-50263.patch
170+Patch6083: backport-0001-CVE-2026-50264.patch
171+Patch6084: backport-0002-CVE-2026-50264.patch
163 172 
164BuildRequires: audit-libs-devel autoconf automake bison dbus-devel flex flex-devel git gcc173BuildRequires: audit-libs-devel autoconf automake bison dbus-devel flex flex-devel git gcc
165BuildRequires: systemtap-sdt-devel libtool pkgconfig 174BuildRequires: systemtap-sdt-devel libtool pkgconfig
@@ -403,6 +412,9 @@ find %{inst_srcdir}/hw/xfree86 -name \*.c -delete
403%{_libdir}/xorg/protocol.txt412%{_libdir}/xorg/protocol.txt
404 413 
405%changelog414%changelog
415+* Mon Jun 08 2026 lingsheng <ultra_planet@qq.com> - 1.20.8-38
416+- fix 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
417+ 
406* Fri Apr 24 2026 lingsheng <ultra_planet@qq.com> - 1.20.8-37418* Fri Apr 24 2026 lingsheng <ultra_planet@qq.com> - 1.20.8-37
407- fix CVE-2026-33999 CVE-2026-34000 CVE-2026-34001 CVE-2026-34002 CVE-2026-34003419- fix CVE-2026-33999 CVE-2026-34000 CVE-2026-34001 CVE-2026-34002 CVE-2026-34003
408 420