Compare commits

...

No commits in common. "imports/c9-beta/xorg-x11-server-Xwayland-21.1.1-6.el9" and "c8-beta" have entirely different histories.

68 changed files with 2627 additions and 3421 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/xwayland-21.1.1.tar.xz
SOURCES/xwayland-21.1.3.tar.xz

View File

@ -1 +1 @@
4eb5e22033c0c80c35480c9466e8041e914cac3a SOURCES/xwayland-21.1.1.tar.xz
ae980a7deeb7cad9f3cd253f3b1ddca5bb26aafa SOURCES/xwayland-21.1.3.tar.xz

View File

@ -0,0 +1,77 @@
From 19e9f199950aaa4b9b7696936d1b067475da999c Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 28 Nov 2023 15:19:04 +1000
Subject: [PATCH xserver] Xi: allocate enough XkbActions for our buttons
button->xkb_acts is supposed to be an array sufficiently large for all
our buttons, not just a single XkbActions struct. Allocating
insufficient memory here means when we memcpy() later in
XkbSetDeviceInfo we write into memory that wasn't ours to begin with,
leading to the usual security ooopsiedaisies.
CVE-2023-6377, ZDI-CAN-22412, ZDI-CAN-22413
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit 0c1a93d319558fe3ab2d94f51d174b4f93810afd)
---
Xi/exevents.c | 12 ++++++------
dix/devices.c | 10 ++++++++++
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/Xi/exevents.c b/Xi/exevents.c
index dcd4efb3b..54ea11a93 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -611,13 +611,13 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
}
if (from->button->xkb_acts) {
- if (!to->button->xkb_acts) {
- to->button->xkb_acts = calloc(1, sizeof(XkbAction));
- if (!to->button->xkb_acts)
- FatalError("[Xi] not enough memory for xkb_acts.\n");
- }
+ size_t maxbuttons = max(to->button->numButtons, from->button->numButtons);
+ to->button->xkb_acts = xnfreallocarray(to->button->xkb_acts,
+ maxbuttons,
+ sizeof(XkbAction));
+ memset(to->button->xkb_acts, 0, maxbuttons * sizeof(XkbAction));
memcpy(to->button->xkb_acts, from->button->xkb_acts,
- sizeof(XkbAction));
+ from->button->numButtons * sizeof(XkbAction));
}
else {
free(to->button->xkb_acts);
diff --git a/dix/devices.c b/dix/devices.c
index 7150734a5..20fef1692 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2530,6 +2530,8 @@ RecalculateMasterButtons(DeviceIntPtr slave)
if (master->button && master->button->numButtons != maxbuttons) {
int i;
+ int last_num_buttons = master->button->numButtons;
+
DeviceChangedEvent event = {
.header = ET_Internal,
.type = ET_DeviceChanged,
@@ -2540,6 +2542,14 @@ RecalculateMasterButtons(DeviceIntPtr slave)
};
master->button->numButtons = maxbuttons;
+ if (last_num_buttons < maxbuttons) {
+ master->button->xkb_acts = xnfreallocarray(master->button->xkb_acts,
+ maxbuttons,
+ sizeof(XkbAction));
+ memset(&master->button->xkb_acts[last_num_buttons],
+ 0,
+ (maxbuttons - last_num_buttons) * sizeof(XkbAction));
+ }
memcpy(&event.buttons.names, master->button->labels, maxbuttons *
sizeof(Atom));
--
2.43.0

View File

@ -0,0 +1,36 @@
From 8660dd164882ce5fc1f274427e2ff3dc020d6273 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Wed, 25 Jan 2023 11:41:40 +1000
Subject: [PATCH xserver] Xi: fix potential use-after-free in
DeepCopyPointerClasses
CVE-2023-0494, ZDI-CAN-19596
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 0ba6d8c37071131a49790243cdac55392ecf71ec)
---
Xi/exevents.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 217baa956..dcd4efb3b 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -619,8 +619,10 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
memcpy(to->button->xkb_acts, from->button->xkb_acts,
sizeof(XkbAction));
}
- else
+ else {
free(to->button->xkb_acts);
+ to->button->xkb_acts = NULL;
+ }
memcpy(to->button->labels, from->button->labels,
from->button->numButtons * sizeof(Atom));
--
2.39.1

View File

@ -0,0 +1,81 @@
From 1e8478455458e998dd366d2cd23d2aeab2bdeee5 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 3 Oct 2023 11:53:05 +1000
Subject: [PATCH xserver] Xi/randr: fix handling of PropModeAppend/Prepend
The handling of appending/prepending properties was incorrect, with at
least two bugs: the property length was set to the length of the new
part only, i.e. appending or prepending N elements to a property with P
existing elements always resulted in the property having N elements
instead of N + P.
Second, when pre-pending a value to a property, the offset for the old
values was incorrect, leaving the new property with potentially
uninitalized values and/or resulting in OOB memory writes.
For example, prepending a 3 element value to a 5 element property would
result in this 8 value array:
[N, N, N, ?, ?, P, P, P ] P, P
^OOB write
The XI2 code is a copy/paste of the RandR code, so the bug exists in
both.
CVE-2023-5367, ZDI-CAN-22153
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 541ab2ecd41d4d8689e71855d93e492bc554719a)
---
Xi/xiproperty.c | 4 ++--
randr/rrproperty.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c
index 066ba21fba..d315f04d0e 100644
--- a/Xi/xiproperty.c
+++ b/Xi/xiproperty.c
@@ -730,7 +730,7 @@ XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type,
XIDestroyDeviceProperty(prop);
return BadAlloc;
}
- new_value.size = len;
+ new_value.size = total_len;
new_value.type = type;
new_value.format = format;
@@ -747,7 +747,7 @@ XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type,
case PropModePrepend:
new_data = new_value.data;
old_data = (void *) (((char *) new_value.data) +
- (prop_value->size * size_in_bytes));
+ (len * size_in_bytes));
break;
}
if (new_data)
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index c2fb9585c6..25469f57b2 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -209,7 +209,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type,
RRDestroyOutputProperty(prop);
return BadAlloc;
}
- new_value.size = len;
+ new_value.size = total_len;
new_value.type = type;
new_value.format = format;
@@ -226,7 +226,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type,
case PropModePrepend:
new_data = new_value.data;
old_data = (void *) (((char *) new_value.data) +
- (prop_value->size * size_in_bytes));
+ (len * size_in_bytes));
break;
}
if (new_data)
--
2.41.0

View File

@ -0,0 +1,51 @@
From 8dba686dc277d6d262ad0c77b4632a5b276697ba Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 29 Nov 2022 12:55:45 +1000
Subject: [PATCH xserver 1/7] Xtest: disallow GenericEvents in
XTestSwapFakeInput
XTestSwapFakeInput assumes all events in this request are
sizeof(xEvent) and iterates through these in 32-byte increments.
However, a GenericEvent may be of arbitrary length longer than 32 bytes,
so any GenericEvent in this list would result in subsequent events to be
misparsed.
Additional, the swapped event is written into a stack-allocated struct
xEvent (size 32 bytes). For any GenericEvent longer than 32 bytes,
swapping the event may thus smash the stack like an avocado on toast.
Catch this case early and return BadValue for any GenericEvent.
Which is what would happen in unswapped setups anyway since XTest
doesn't support GenericEvent.
CVE-2022-46340, ZDI-CAN 19265
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
Xext/xtest.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Xext/xtest.c b/Xext/xtest.c
index bf27eb590b..2985a4ce6e 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -502,10 +502,11 @@ XTestSwapFakeInput(ClientPtr client, xReq * req)
nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) {
+ int evtype = ev->u.u.type & 0x177;
/* Swap event */
- proc = EventSwapVector[ev->u.u.type & 0177];
+ proc = EventSwapVector[evtype];
/* no swapping proc; invalid event type? */
- if (!proc || proc == NotImplemented) {
+ if (!proc || proc == NotImplemented || evtype == GenericEvent) {
client->errorValue = ev->u.u.type;
return BadValue;
}
--
2.38.1

View File

@ -0,0 +1,42 @@
From 26ef545b3502f61ca722a7a3373507e88ef64110 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 13 Mar 2023 11:08:47 +0100
Subject: [PATCH xserver] composite: Fix use-after-free of the COW
ZDI-CAN-19866/CVE-2023-1393
If a client explicitly destroys the compositor overlay window (aka COW),
we would leave a dangling pointer to that window in the CompScreen
structure, which will trigger a use-after-free later.
Make sure to clear the CompScreen pointer to the COW when the latter gets
destroyed explicitly by the client.
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
---
composite/compwindow.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 4e2494b86..b30da589e 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -620,6 +620,11 @@ compDestroyWindow(WindowPtr pWin)
ret = (*pScreen->DestroyWindow) (pWin);
cs->DestroyWindow = pScreen->DestroyWindow;
pScreen->DestroyWindow = compDestroyWindow;
+
+ /* Did we just destroy the overlay window? */
+ if (pWin == cs->pOverlayWin)
+ cs->pOverlayWin = NULL;
+
/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
return ret;
}
--
2.40.0

View File

@ -0,0 +1,54 @@
From b5cb27032d3e486ba84a491e1420e85171c4c0a3 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Thu, 14 Dec 2023 11:29:49 +1000
Subject: [PATCH xserver 1/9] dix: allocate enough space for logical button
maps
Both DeviceFocusEvent and the XIQueryPointer reply contain a bit for
each logical button currently down. Since buttons can be arbitrarily mapped
to anything up to 255 make sure we have enough bits for the maximum mapping.
CVE-2023-6816, ZDI-CAN-22664, ZDI-CAN-22665
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit 9e2ecb2af8302dedc49cb6a63ebe063c58a9e7e3)
---
Xi/xiquerypointer.c | 3 +--
dix/enterleave.c | 5 +++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Xi/xiquerypointer.c b/Xi/xiquerypointer.c
index 5b77b1a44..2b05ac5f3 100644
--- a/Xi/xiquerypointer.c
+++ b/Xi/xiquerypointer.c
@@ -149,8 +149,7 @@ ProcXIQueryPointer(ClientPtr client)
if (pDev->button) {
int i;
- rep.buttons_len =
- bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
+ rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */
rep.length += rep.buttons_len;
buttons = calloc(rep.buttons_len, 4);
if (!buttons)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index 867ec7436..ded8679d7 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -784,8 +784,9 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
- /* XI 2 event */
- btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
+ /* XI 2 event contains the logical button map - maps are CARD8
+ * so we need 256 bits for the possibly maximum mapping */
+ btlen = (mouse->button) ? bits_to_bytes(256) : 0;
btlen = bytes_to_int32(btlen);
len = sizeof(xXIFocusInEvent) + btlen * 4;
--
2.43.0

View File

@ -0,0 +1,105 @@
From b98fc07d3442a289c6bef82df50dd0a2d01de71a Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@redhat.com>
Date: Thu, 2 Feb 2023 12:26:27 -0500
Subject: [PATCH xserver] present: Send a PresentConfigureNotify event for
destroyed windows
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This enables fixing a deadlock case on the client side, where the client
ends up blocked waiting for a Present event that will never come because
the window was destroyed. The new PresentWindowDestroyed flag allows the
client to avoid blocking indefinitely.
Signed-off-by: Adam Jackson <ajax@redhat.com>
See-also: https://gitlab.freedesktop.org/mesa/mesa/-/issues/116
See-also: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6685
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 462b06033e66a32308d940eb5fc47f5e4c914dc0)
---
present/present_event.c | 5 +++--
present/present_priv.h | 7 ++++++-
present/present_screen.c | 11 ++++++++++-
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/present/present_event.c b/present/present_event.c
index 435b26b70..849732dc8 100644
--- a/present/present_event.c
+++ b/present/present_event.c
@@ -102,7 +102,8 @@ present_event_swap(xGenericEvent *from, xGenericEvent *to)
}
void
-present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h,
+ int bw, WindowPtr sibling, CARD32 flags)
{
present_window_priv_ptr window_priv = present_window_priv(window);
@@ -122,7 +123,7 @@ present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw,
.off_y = 0,
.pixmap_width = w,
.pixmap_height = h,
- .pixmap_flags = 0
+ .pixmap_flags = flags
};
present_event_ptr event;
diff --git a/present/present_priv.h b/present/present_priv.h
index 6ebd009a2..4ad729864 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -43,6 +43,11 @@
#define DebugPresent(x)
#endif
+/* XXX this belongs in presentproto */
+#ifndef PresentWindowDestroyed
+#define PresentWindowDestroyed (1 << 0)
+#endif
+
extern int present_request;
extern DevPrivateKeyRec present_screen_private_key;
@@ -307,7 +312,7 @@ void
present_free_events(WindowPtr window);
void
-present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling);
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling, CARD32 flags);
void
present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc);
diff --git a/present/present_screen.c b/present/present_screen.c
index 15684eda4..2c29aafd2 100644
--- a/present/present_screen.c
+++ b/present/present_screen.c
@@ -93,6 +93,15 @@ present_destroy_window(WindowPtr window)
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
present_window_priv_ptr window_priv = present_window_priv(window);
+ present_send_config_notify(window,
+ window->drawable.x,
+ window->drawable.y,
+ window->drawable.width,
+ window->drawable.height,
+ window->borderWidth,
+ window->nextSib,
+ PresentWindowDestroyed);
+
if (window_priv) {
present_clear_window_notifies(window);
present_free_events(window);
@@ -123,7 +132,7 @@ present_config_notify(WindowPtr window,
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
- present_send_config_notify(window, x, y, w, h, bw, sibling);
+ present_send_config_notify(window, x, y, w, h, bw, sibling, 0);
unwrap(screen_priv, screen, ConfigNotify);
if (screen->ConfigNotify)
--
2.40.0

View File

@ -0,0 +1,61 @@
From aaf854fb25541380cc38a221c15f0e8372f48872 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 27 Nov 2023 16:27:49 +1000
Subject: [PATCH xserver] randr: avoid integer truncation in length check of
ProcRRChange*Property
Affected are ProcRRChangeProviderProperty and ProcRRChangeOutputProperty.
See also xserver@8f454b79 where this same bug was fixed for the core
protocol and XI.
This fixes an OOB read and the resulting information disclosure.
Length calculation for the request was clipped to a 32-bit integer. With
the correct stuff->nUnits value the expected request size was
truncated, passing the REQUEST_FIXED_SIZE check.
The server then proceeded with reading at least stuff->num_items bytes
(depending on stuff->format) from the request and stuffing whatever it
finds into the property. In the process it would also allocate at least
stuff->nUnits bytes, i.e. 4GB.
CVE-2023-6478, ZDI-CAN-22561
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit 14f480010a93ff962fef66a16412fafff81ad632)
---
randr/rrproperty.c | 2 +-
randr/rrproviderproperty.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 25469f57b..c4fef8a1f 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -530,7 +530,7 @@ ProcRRChangeOutputProperty(ClientPtr client)
char format, mode;
unsigned long len;
int sizeInBytes;
- int totalSize;
+ uint64_t totalSize;
int err;
REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq);
diff --git a/randr/rrproviderproperty.c b/randr/rrproviderproperty.c
index b79c17f9b..90c5a9a93 100644
--- a/randr/rrproviderproperty.c
+++ b/randr/rrproviderproperty.c
@@ -498,7 +498,7 @@ ProcRRChangeProviderProperty(ClientPtr client)
char format, mode;
unsigned long len;
int sizeInBytes;
- int totalSize;
+ uint64_t totalSize;
int err;
REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq);
--
2.43.0

View File

@ -0,0 +1,35 @@
From a8644465d98beb08759546711b77bb617861c67f Mon Sep 17 00:00:00 2001
From: Povilas Kanapickas <povilas@radix.lt>
Date: Tue, 14 Dec 2021 15:00:00 +0200
Subject: [PATCH xserver 1/4] record: Fix out of bounds access in
SwapCreateRegister()
ZDI-CAN-14952, CVE-2021-4011
This vulnerability was discovered and the fix was suggested by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
(cherry picked from commit e56f61c79fc3cee26d83cda0f84ae56d5979f768)
---
record/record.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/record/record.c b/record/record.c
index be154525d..e123867a7 100644
--- a/record/record.c
+++ b/record/record.c
@@ -2516,8 +2516,8 @@ SwapCreateRegister(ClientPtr client, xRecordRegisterClientsReq * stuff)
swapl(pClientID);
}
if (stuff->nRanges >
- client->req_len - bytes_to_int32(sz_xRecordRegisterClientsReq)
- - stuff->nClients)
+ (client->req_len - bytes_to_int32(sz_xRecordRegisterClientsReq)
+ - stuff->nClients) / bytes_to_int32(sz_xRecordRange))
return BadLength;
RecordSwapRanges((xRecordRange *) pClientID, stuff->nRanges);
return Success;
--
2.33.1

View File

@ -0,0 +1,59 @@
From 18f91b950e22c2a342a4fbc55e9ddf7534a707d2 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Wed, 13 Jul 2022 11:23:09 +1000
Subject: [PATCH xserver] xkb: fix some possible memleaks in XkbGetKbdByName
GetComponentByName returns an allocated string, so let's free that if we
fail somewhere.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
xkb/xkb.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 4692895db..b79a269e3 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5935,18 +5935,32 @@ ProcXkbGetKbdByName(ClientPtr client)
xkb = dev->key->xkbInfo->desc;
status = Success;
str = (unsigned char *) &stuff[1];
- if (GetComponentSpec(&str, TRUE, &status)) /* keymap, unsupported */
- return BadMatch;
+ {
+ char *keymap = GetComponentSpec(&str, TRUE, &status); /* keymap, unsupported */
+ if (keymap) {
+ free(keymap);
+ return BadMatch;
+ }
+ }
names.keycodes = GetComponentSpec(&str, TRUE, &status);
names.types = GetComponentSpec(&str, TRUE, &status);
names.compat = GetComponentSpec(&str, TRUE, &status);
names.symbols = GetComponentSpec(&str, TRUE, &status);
names.geometry = GetComponentSpec(&str, TRUE, &status);
- if (status != Success)
+ if (status == Success) {
+ len = str - ((unsigned char *) stuff);
+ if ((XkbPaddedSize(len) / 4) != stuff->length)
+ status = BadLength;
+ }
+
+ if (status != Success) {
+ free(names.keycodes);
+ free(names.types);
+ free(names.compat);
+ free(names.symbols);
+ free(names.geometry);
return status;
- len = str - ((unsigned char *) stuff);
- if ((XkbPaddedSize(len) / 4) != stuff->length)
- return BadLength;
+ }
CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
--
2.38.1

View File

@ -0,0 +1,35 @@
From 11beef0b7f1ed290348e45618e5fa0d2bffcb72e Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 5 Jul 2022 12:06:20 +1000
Subject: [PATCH xserver] xkb: proof GetCountedString against request length
attacks
GetCountedString did a check for the whole string to be within the
request buffer but not for the initial 2 bytes that contain the length
field. A swapped client could send a malformed request to trigger a
swaps() on those bytes, writing into random memory.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
xkb/xkb.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/xkb/xkb.c b/xkb/xkb.c
index f42f59ef3..1841cff26 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5137,6 +5137,11 @@ _GetCountedString(char **wire_inout, ClientPtr client, char **str)
CARD16 len;
wire = *wire_inout;
+
+ if (client->req_len <
+ bytes_to_int32(wire + 2 - (char *) client->requestBuffer))
+ return BadValue;
+
len = *(CARD16 *) wire;
if (client->swapped) {
swaps(&len);
--
2.38.1

View File

@ -0,0 +1,77 @@
From c9b379ec5a1a34692af06056925bd0fc5f809713 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 5 Jul 2022 12:40:47 +1000
Subject: [PATCH xserver 1/3] xkb: switch to array index loops to moving
pointers
Most similar loops here use a pointer that advances with each loop
iteration, let's do the same here for consistency.
No functional changes.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
(cherry picked from commit f1070c01d616c5f21f939d5ebc533738779451ac)
---
xkb/xkb.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/xkb/xkb.c b/xkb/xkb.c
index d056c698c..684394d77 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5372,16 +5372,16 @@ _CheckSetSections(XkbGeometryPtr geom,
row->left = rWire->left;
row->vertical = rWire->vertical;
kWire = (xkbKeyWireDesc *) &rWire[1];
- for (k = 0; k < rWire->nKeys; k++) {
+ for (k = 0; k < rWire->nKeys; k++, kWire++) {
XkbKeyPtr key;
key = XkbAddGeomKey(row);
if (!key)
return BadAlloc;
- memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
- key->gap = kWire[k].gap;
- key->shape_ndx = kWire[k].shapeNdx;
- key->color_ndx = kWire[k].colorNdx;
+ memcpy(key->name.name, kWire->name, XkbKeyNameLength);
+ key->gap = kWire->gap;
+ key->shape_ndx = kWire->shapeNdx;
+ key->color_ndx = kWire->colorNdx;
if (key->shape_ndx >= geom->num_shapes) {
client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
geom->num_shapes);
@@ -5393,7 +5393,7 @@ _CheckSetSections(XkbGeometryPtr geom,
return BadMatch;
}
}
- rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
+ rWire = (xkbRowWireDesc *)kWire;
}
wire = (char *) rWire;
if (sWire->nDoodads > 0) {
@@ -5458,16 +5458,16 @@ _CheckSetShapes(XkbGeometryPtr geom,
return BadAlloc;
ol->corner_radius = olWire->cornerRadius;
ptWire = (xkbPointWireDesc *) &olWire[1];
- for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
- pt->x = ptWire[p].x;
- pt->y = ptWire[p].y;
+ for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++, ptWire++) {
+ pt->x = ptWire->x;
+ pt->y = ptWire->y;
if (client->swapped) {
swaps(&pt->x);
swaps(&pt->y);
}
}
ol->num_points = olWire->nPoints;
- olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
+ olWire = (xkbOutlineWireDesc *)ptWire;
}
if (shapeWire->primaryNdx != XkbNoShape)
shape->primary = &shape->outlines[shapeWire->primaryNdx];
--
2.36.1

View File

@ -1,257 +0,0 @@
From c7853c6de126f6794946c592deed205c0ddad2d9 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 3 Mar 2021 09:55:12 +0100
Subject: [PATCH xserver 01/27] xwayland: Move dmabuf interface to common
glamor code
This is preliminary work for hardware accelerated rendering with the
NVIDIA driver.
The EGLStream backend can possibly also use the dmabuf interface, so
move the relevant code from the GBM specific source to the common bits.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
(cherry picked from commit ae225417c0a0828ffb24e11eb4b968c34692e25a)
---
hw/xwayland/xwayland-glamor-gbm.c | 73 ++---------------------------
hw/xwayland/xwayland-glamor.c | 76 +++++++++++++++++++++++++++++--
hw/xwayland/xwayland-screen.h | 1 +
3 files changed, 76 insertions(+), 74 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 221bf268a..73c69727e 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -56,7 +56,6 @@ struct xwl_gbm_private {
char *device_name;
struct gbm_device *gbm;
struct wl_drm *drm;
- struct zwp_linux_dmabuf_v1 *dmabuf;
int drm_fd;
int fd_render_node;
Bool drm_authenticated;
@@ -334,10 +333,10 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
}
}
- if (xwl_gbm->dmabuf && modifier_supported) {
+ if (xwl_screen->dmabuf && modifier_supported) {
struct zwp_linux_buffer_params_v1 *params;
- params = zwp_linux_dmabuf_v1_create_params(xwl_gbm->dmabuf);
+ params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
for (i = 0; i < num_planes; i++) {
zwp_linux_buffer_params_v1_add(params, prime_fd, i,
offsets[i], strides[i],
@@ -604,7 +603,7 @@ glamor_get_formats(ScreenPtr screen,
/* Explicitly zero the count as the caller may ignore the return value */
*num_formats = 0;
- if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
+ if (!xwl_gbm->dmabuf_capable || !xwl_screen->dmabuf)
return FALSE;
if (xwl_screen->num_formats == 0)
@@ -633,7 +632,7 @@ glamor_get_modifiers(ScreenPtr screen, uint32_t format,
/* Explicitly zero the count as the caller may ignore the return value */
*num_modifiers = 0;
- if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
+ if (!xwl_gbm->dmabuf_capable || !xwl_screen->dmabuf)
return FALSE;
if (xwl_screen->num_formats == 0)
@@ -797,54 +796,6 @@ static const struct wl_drm_listener xwl_drm_listener = {
xwl_drm_handle_capabilities
};
-static void
-xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
- uint32_t format)
-{
-}
-
-static void
-xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
- uint32_t format, uint32_t modifier_hi,
- uint32_t modifier_lo)
-{
- struct xwl_screen *xwl_screen = data;
- struct xwl_format *xwl_format = NULL;
- int i;
-
- for (i = 0; i < xwl_screen->num_formats; i++) {
- if (xwl_screen->formats[i].format == format) {
- xwl_format = &xwl_screen->formats[i];
- break;
- }
- }
-
- if (xwl_format == NULL) {
- xwl_screen->num_formats++;
- xwl_screen->formats = realloc(xwl_screen->formats,
- xwl_screen->num_formats * sizeof(*xwl_format));
- if (!xwl_screen->formats)
- return;
- xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
- xwl_format->format = format;
- xwl_format->num_modifiers = 0;
- xwl_format->modifiers = NULL;
- }
-
- xwl_format->num_modifiers++;
- xwl_format->modifiers = realloc(xwl_format->modifiers,
- xwl_format->num_modifiers * sizeof(uint64_t));
- if (!xwl_format->modifiers)
- return;
- xwl_format->modifiers[xwl_format->num_modifiers - 1] = (uint64_t) modifier_lo;
- xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
-}
-
-static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
- .format = xwl_dmabuf_handle_format,
- .modifier = xwl_dmabuf_handle_modifier
-};
-
Bool
xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
uint32_t id, uint32_t version)
@@ -862,22 +813,6 @@ xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
return TRUE;
}
-Bool
-xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
- uint32_t id, uint32_t version)
-{
- struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
-
- if (version < 3)
- return FALSE;
-
- xwl_gbm->dmabuf =
- wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
- zwp_linux_dmabuf_v1_add_listener(xwl_gbm->dmabuf, &xwl_dmabuf_listener, xwl_screen);
-
- return TRUE;
-}
-
static Bool
xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen,
struct wl_registry *wl_registry,
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index bcd07a1a5..cce0c911e 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -35,6 +35,10 @@
#include "glx_extinit.h"
#endif
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
+#include "drm-client-protocol.h"
+#include <drm_fourcc.h>
+
#include "xwayland-glamor.h"
#include "xwayland-glx.h"
#include "xwayland-screen.h"
@@ -75,6 +79,68 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
xwl_screen->glamor_ctx = glamor_ctx;
}
+static void
+xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
+ uint32_t format)
+{
+}
+
+static void
+xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
+ uint32_t format, uint32_t modifier_hi,
+ uint32_t modifier_lo)
+{
+ struct xwl_screen *xwl_screen = data;
+ struct xwl_format *xwl_format = NULL;
+ int i;
+
+ for (i = 0; i < xwl_screen->num_formats; i++) {
+ if (xwl_screen->formats[i].format == format) {
+ xwl_format = &xwl_screen->formats[i];
+ break;
+ }
+ }
+
+ if (xwl_format == NULL) {
+ xwl_screen->num_formats++;
+ xwl_screen->formats = realloc(xwl_screen->formats,
+ xwl_screen->num_formats * sizeof(*xwl_format));
+ if (!xwl_screen->formats)
+ return;
+ xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
+ xwl_format->format = format;
+ xwl_format->num_modifiers = 0;
+ xwl_format->modifiers = NULL;
+ }
+
+ xwl_format->num_modifiers++;
+ xwl_format->modifiers = realloc(xwl_format->modifiers,
+ xwl_format->num_modifiers * sizeof(uint64_t));
+ if (!xwl_format->modifiers)
+ return;
+ xwl_format->modifiers[xwl_format->num_modifiers - 1] = (uint64_t) modifier_lo;
+ xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
+}
+
+static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
+ .format = xwl_dmabuf_handle_format,
+ .modifier = xwl_dmabuf_handle_modifier
+};
+
+Bool
+xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version)
+{
+ if (version < 3)
+ return FALSE;
+
+ xwl_screen->dmabuf =
+ wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
+ zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen);
+
+ return TRUE;
+}
+
void
xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
struct wl_registry *registry,
@@ -89,11 +155,11 @@ xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
version)) {
/* no-op */
} else if (xwl_screen->eglstream_backend.is_available &&
- xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
- registry,
- id,
- interface,
- version)) {
+ xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
+ registry,
+ id,
+ interface,
+ version)) {
/* no-op */
}
}
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 8d0b12705..5fe4712bd 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -83,6 +83,7 @@ struct xwl_screen {
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
+ struct zwp_linux_dmabuf_v1 *dmabuf;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct wp_viewporter *viewporter;
uint32_t serial;
--
2.31.1

View File

@ -0,0 +1,43 @@
From 0a7ed9ff7ea20f7b958a2ad9f9bd045080a3ad9a Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 15 Nov 2021 16:02:34 +0100
Subject: [PATCH xserver 1/4] xwayland/eglstream: Demote EGLstream device
warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If no EGLstream capable device is found at startup, Xwayland's EGLstream
backend will log an error message "glamor: No eglstream capable devices
found".
However, considering that the vast majority of drivers do not implement
EGLstream, the lack of EGLstream capable device is more of the norm than
the exception.
Change the error message to a log verbose message.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
(cherry picked from commit 96c82befa2c3f3dc3534743c67cc003c2106e9b0)
---
hw/xwayland/xwayland-glamor-eglstream.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 8d18caaf5..93d192d58 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -1144,7 +1144,7 @@ xwl_eglstream_get_device(struct xwl_screen *xwl_screen)
free(devices);
out:
if (!device)
- ErrorF("glamor: No eglstream capable devices found\n");
+ LogMessageVerb(X_INFO, 3, "glamor: No eglstream capable devices found\n");
return device;
}
--
2.33.1

View File

@ -1,36 +0,0 @@
From 8c74023712a9e0d79ec669738b726e7dc821de68 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 23 Jun 2021 11:35:17 +0200
Subject: [PATCH xserver 1/2] xwayland/eglstream: Keep pending stream if the
pixmap didn't change
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If the pixmap does not actually change in set_window_pixmap(), there is
no need to invalidate the pending stream, if there's one.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Suggested-by: Michel Dänzer <mdaenzer@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 2be9f795bc15012dc912f595003e01bb6aa66f54)
---
hw/xwayland/xwayland-glamor-eglstream.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 0affc954c..2eae9494c 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -377,7 +377,7 @@ xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
* attached, so the stream would be useless.
*/
old_pixmap = (*screen->GetWindowPixmap) (window);
- if (old_pixmap)
+ if (old_pixmap && old_pixmap != pixmap)
xwl_eglstream_maybe_set_pending_stream_invalid(old_pixmap);
xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
--
2.31.1

View File

@ -0,0 +1,40 @@
From c5ff57676698f19ed3a1402aef58a15552e32d27 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 29 Nov 2022 13:24:00 +1000
Subject: [PATCH xserver 2/7] Xi: return an error from XI property changes if
verification failed
Both ProcXChangeDeviceProperty and ProcXIChangeProperty checked the
property for validity but didn't actually return the potential error.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
Xi/xiproperty.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c
index a36f7d61df..68c362c628 100644
--- a/Xi/xiproperty.c
+++ b/Xi/xiproperty.c
@@ -902,6 +902,8 @@ ProcXChangeDeviceProperty(ClientPtr client)
rc = check_change_property(client, stuff->property, stuff->type,
stuff->format, stuff->mode, stuff->nUnits);
+ if (rc != Success)
+ return rc;
len = stuff->nUnits;
if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
@@ -1141,6 +1143,9 @@ ProcXIChangeProperty(ClientPtr client)
rc = check_change_property(client, stuff->property, stuff->type,
stuff->format, stuff->mode, stuff->num_items);
+ if (rc != Success)
+ return rc;
+
len = stuff->num_items;
if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
return BadLength;
--
2.38.1

View File

@ -0,0 +1,86 @@
From 9105be1c51d6973dc8d7806108349bc152029ec5 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 18 Dec 2023 14:27:50 +1000
Subject: [PATCH xserver 2/9] dix: Allocate sufficient xEvents for our
DeviceStateNotify
If a device has both a button class and a key class and numButtons is
zero, we can get an OOB write due to event under-allocation.
This function seems to assume a device has either keys or buttons, not
both. It has two virtually identical code paths, both of which assume
they're applying to the first event in the sequence.
A device with both a key and button class triggered a logic bug - only
one xEvent was allocated but the deviceStateNotify pointer was pushed on
once per type. So effectively this logic code:
int count = 1;
if (button && nbuttons > 32) count++;
if (key && nbuttons > 0) count++;
if (key && nkeys > 32) count++; // this is basically always true
// count is at 2 for our keys + zero button device
ev = alloc(count * sizeof(xEvent));
FixDeviceStateNotify(ev);
if (button)
FixDeviceStateNotify(ev++);
if (key)
FixDeviceStateNotify(ev++); // santa drops into the wrong chimney here
If the device has more than 3 valuators, the OOB is pushed back - we're
off by one so it will happen when the last deviceValuator event is
written instead.
Fix this by allocating the maximum number of events we may allocate.
Note that the current behavior is not protocol-correct anyway, this
patch fixes only the allocation issue.
Note that this issue does not trigger if the device has at least one
button. While the server does not prevent a button class with zero
buttons, it is very unlikely.
CVE-2024-0229, ZDI-CAN-22678
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit ece23be888a93b741aa1209d1dbf64636109d6a5)
---
dix/enterleave.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index ded8679d7..17964b00a 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -675,7 +675,8 @@ static void
DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
{
int evcount = 1;
- deviceStateNotify *ev, *sev;
+ deviceStateNotify sev[6 + (MAX_VALUATORS + 2)/3];
+ deviceStateNotify *ev;
deviceKeyStateNotify *kev;
deviceButtonStateNotify *bev;
@@ -714,7 +715,7 @@ DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
}
}
- sev = ev = xallocarray(evcount, sizeof(xEvent));
+ ev = sev;
FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
if (b != NULL) {
@@ -770,7 +771,6 @@ DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
DeviceStateNotifyMask, NullGrab);
- free(sev);
}
void
--
2.43.0

View File

@ -0,0 +1,44 @@
From 3eb5445f6f7fa9f86de87adc768105d42bdbcf74 Mon Sep 17 00:00:00 2001
From: Povilas Kanapickas <povilas@radix.lt>
Date: Tue, 14 Dec 2021 15:00:01 +0200
Subject: [PATCH xserver 2/4] xfixes: Fix out of bounds access in
*ProcXFixesCreatePointerBarrier()
ZDI-CAN-14950, CVE-2021-4009
This vulnerability was discovered and the fix was suggested by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
(cherry picked from commit b5196750099ae6ae582e1f46bd0a6dad29550e02)
---
xfixes/cursor.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index 60580b88f..c5d4554b2 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -1010,7 +1010,8 @@ ProcXFixesCreatePointerBarrier(ClientPtr client)
{
REQUEST(xXFixesCreatePointerBarrierReq);
- REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
+ REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
+ pad_to_int32(stuff->num_devices * sizeof(CARD16)));
LEGAL_NEW_RESOURCE(stuff->barrier, client);
return XICreatePointerBarrier(client, stuff);
@@ -1027,7 +1028,8 @@ SProcXFixesCreatePointerBarrier(ClientPtr client)
swaps(&stuff->length);
swaps(&stuff->num_devices);
- REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
+ REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
+ pad_to_int32(stuff->num_devices * sizeof(CARD16)));
swapl(&stuff->barrier);
swapl(&stuff->window);
--
2.33.1

View File

@ -0,0 +1,180 @@
From 45a0af83129eb7dc244c5118360afc1972a686c7 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 5 Jul 2022 09:50:41 +1000
Subject: [PATCH xserver 2/3] xkb: swap XkbSetDeviceInfo and
XkbSetDeviceInfoCheck
XKB often uses a FooCheck and Foo function pair, the former is supposed
to check all values in the request and error out on BadLength,
BadValue, etc. The latter is then called once we're confident the values
are good (they may still fail on an individual device, but that's a
different topic).
In the case of XkbSetDeviceInfo, those functions were incorrectly
named, with XkbSetDeviceInfo ending up as the checker function and
XkbSetDeviceInfoCheck as the setter function. As a result, the setter
function was called before the checker function, accessing request
data and modifying device state before we ensured that the data is
valid.
In particular, the setter function relied on values being already
byte-swapped. This in turn could lead to potential OOB memory access.
Fix this by correctly naming the functions and moving the length checks
over to the checker function. These were added in 87c64fc5b0 to the
wrong function, probably due to the incorrect naming.
Fixes ZDI-CAN 16070, CVE-2022-2320.
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Introduced in c06e27b2f6fd9f7b9f827623a48876a225264132
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit dd8caf39e9e15d8f302e54045dd08d8ebf1025dc)
---
xkb/xkb.c | 46 +++++++++++++++++++++++++---------------------
1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 684394d77..36464a770 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -6554,7 +6554,8 @@ ProcXkbGetDeviceInfo(ClientPtr client)
static char *
CheckSetDeviceIndicators(char *wire,
DeviceIntPtr dev,
- int num, int *status_rtrn, ClientPtr client)
+ int num, int *status_rtrn, ClientPtr client,
+ xkbSetDeviceInfoReq * stuff)
{
xkbDeviceLedsWireDesc *ledWire;
int i;
@@ -6562,6 +6563,11 @@ CheckSetDeviceIndicators(char *wire,
ledWire = (xkbDeviceLedsWireDesc *) wire;
for (i = 0; i < num; i++) {
+ if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
+ *status_rtrn = BadLength;
+ return (char *) ledWire;
+ }
+
if (client->swapped) {
swaps(&ledWire->ledClass);
swaps(&ledWire->ledID);
@@ -6589,6 +6595,11 @@ CheckSetDeviceIndicators(char *wire,
atomWire = (CARD32 *) &ledWire[1];
if (nNames > 0) {
for (n = 0; n < nNames; n++) {
+ if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
+ *status_rtrn = BadLength;
+ return (char *) atomWire;
+ }
+
if (client->swapped) {
swapl(atomWire);
}
@@ -6600,6 +6611,10 @@ CheckSetDeviceIndicators(char *wire,
mapWire = (xkbIndicatorMapWireDesc *) atomWire;
if (nMaps > 0) {
for (n = 0; n < nMaps; n++) {
+ if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) {
+ *status_rtrn = BadLength;
+ return (char *) mapWire;
+ }
if (client->swapped) {
swaps(&mapWire->virtualMods);
swapl(&mapWire->ctrls);
@@ -6651,11 +6666,6 @@ SetDeviceIndicators(char *wire,
xkbIndicatorMapWireDesc *mapWire;
XkbSrvLedInfoPtr sli;
- if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
- *status_rtrn = BadLength;
- return (char *) ledWire;
- }
-
namec = mapc = statec = 0;
sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
XkbXI_IndicatorMapsMask);
@@ -6674,10 +6684,6 @@ SetDeviceIndicators(char *wire,
memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
if (ledWire->namesPresent & bit) {
- if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
- *status_rtrn = BadLength;
- return (char *) atomWire;
- }
sli->names[n] = (Atom) *atomWire;
if (sli->names[n] == None)
ledWire->namesPresent &= ~bit;
@@ -6695,10 +6701,6 @@ SetDeviceIndicators(char *wire,
if (ledWire->mapsPresent) {
for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
if (ledWire->mapsPresent & bit) {
- if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) {
- *status_rtrn = BadLength;
- return (char *) mapWire;
- }
sli->maps[n].flags = mapWire->flags;
sli->maps[n].which_groups = mapWire->whichGroups;
sli->maps[n].groups = mapWire->groups;
@@ -6734,13 +6736,17 @@ SetDeviceIndicators(char *wire,
}
static int
-_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
+_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
xkbSetDeviceInfoReq * stuff)
{
char *wire;
wire = (char *) &stuff[1];
if (stuff->change & XkbXI_ButtonActionsMask) {
+ int sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
+ if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
+ return BadLength;
+
if (!dev->button) {
client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
return XkbKeyboardErrorCode;
@@ -6751,13 +6757,13 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
dev->button->numButtons);
return BadMatch;
}
- wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
+ wire += sz;
}
if (stuff->change & XkbXI_IndicatorsMask) {
int status = Success;
wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
- &status, client);
+ &status, client, stuff);
if (status != Success)
return status;
}
@@ -6768,8 +6774,8 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
}
static int
-_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
- xkbSetDeviceInfoReq * stuff)
+_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
+ xkbSetDeviceInfoReq * stuff)
{
char *wire;
xkbExtensionDeviceNotify ed;
@@ -6793,8 +6799,6 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
if (stuff->firstBtn + stuff->nBtns > nBtns)
return BadValue;
sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
- if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
- return BadLength;
memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
wire += sz;
ed.reason |= XkbXI_ButtonActionsMask;
--
2.36.1

View File

@ -1,292 +0,0 @@
From d9005a02e9c109e57dcc81b51de3b5778915af26 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 30 Apr 2021 09:56:05 +0200
Subject: [PATCH xserver 2/2] xwayland/eglstream: Remove stream validity
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
To avoid an EGL stream in the wrong state, if the window pixmap changed
before the stream was connected, we would still keep the pending stream
but mark it as invalid. Once the callback is received, the pending would
be simply discarded.
But all of this is actually to avoid a bug in egl-wayland, there should
not be any problem with Xwayland destroying an EGL stream while the
compositor is still using it.
With that bug now fixed in egl-wayland 1.1.7, we can safely drop all
that logic from Xwayland EGLstream backend.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1189
(cherry picked from commit 7d509b6f342d9732b567dc4efa867ea24919853b)
---
hw/xwayland/xwayland-glamor-eglstream.c | 165 ++++--------------------
1 file changed, 28 insertions(+), 137 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 2eae9494c..8d18caaf5 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -52,15 +52,6 @@
#include "wayland-eglstream-controller-client-protocol.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
-struct xwl_eglstream_pending_stream {
- PixmapPtr pixmap;
- WindowPtr window;
-
- struct wl_callback *cb;
-
- Bool is_valid;
-};
-
struct xwl_eglstream_private {
EGLDeviceEXT egl_device;
struct wl_eglstream_display *display;
@@ -90,7 +81,7 @@ struct xwl_pixmap {
/* add any new <= 4-byte member here to avoid holes on 64-bit */
struct xwl_screen *xwl_screen;
struct wl_buffer *buffer;
- struct xwl_eglstream_pending_stream *pending_stream;
+ struct wl_callback *pending_cb;
Bool wait_for_buffer_release;
/* XWL_PIXMAP_EGLSTREAM. */
@@ -301,20 +292,12 @@ xwl_eglstream_destroy_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
free(xwl_pixmap);
}
-static void
-xwl_glamor_eglstream_destroy_pending_stream(struct xwl_eglstream_pending_stream *pending)
-{
- if (pending->cb)
- wl_callback_destroy(pending->cb);
- free(pending);
-}
-
static void
xwl_glamor_eglstream_remove_pending_stream(struct xwl_pixmap *xwl_pixmap)
{
- if (xwl_pixmap->pending_stream) {
- xwl_glamor_eglstream_destroy_pending_stream(xwl_pixmap->pending_stream);
- xwl_pixmap->pending_stream = NULL;
+ if (xwl_pixmap->pending_cb) {
+ wl_callback_destroy(xwl_pixmap->pending_cb);
+ xwl_pixmap->pending_cb = NULL;
}
}
@@ -338,27 +321,13 @@ xwl_glamor_eglstream_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
}
static void
-xwl_eglstream_maybe_set_pending_stream_invalid(PixmapPtr pixmap)
+xwl_eglstream_cancel_pending_stream(PixmapPtr pixmap)
{
struct xwl_pixmap *xwl_pixmap;
- struct xwl_eglstream_pending_stream *pending;
xwl_pixmap = xwl_pixmap_get(pixmap);
- if (!xwl_pixmap)
- return;
-
- pending = xwl_pixmap->pending_stream;
- if (!pending)
- return;
-
- pending->is_valid = FALSE;
-
- /* The compositor may still be using the stream, so we can't destroy
- * it yet. We'll only have a guarantee that the stream is safe to
- * destroy once we receive the pending wl_display_sync() for this
- * stream
- */
- pending->pixmap->refcnt++;
+ if (xwl_pixmap)
+ xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
}
static void
@@ -378,7 +347,7 @@ xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
*/
old_pixmap = (*screen->GetWindowPixmap) (window);
if (old_pixmap && old_pixmap != pixmap)
- xwl_eglstream_maybe_set_pending_stream_invalid(old_pixmap);
+ xwl_eglstream_cancel_pending_stream(old_pixmap);
xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
(*xwl_screen->screen->SetWindowPixmap)(window, pixmap);
@@ -464,68 +433,19 @@ xwl_eglstream_print_error(EGLDisplay egl_display,
}
}
-/* Because we run asynchronously with our wayland compositor, it's possible
- * that an X client event could cause us to begin creating a stream for a
- * pixmap/window combo before the stream for the pixmap this window
- * previously used has been fully initialized. An example:
- *
- * - Start processing X client events.
- * - X window receives resize event, causing us to create a new pixmap and
- * begin creating the corresponding eglstream. This pixmap is known as
- * pixmap A.
- * - X window receives another resize event, and again changes its current
- * pixmap causing us to create another corresponding eglstream for the same
- * window. This pixmap is known as pixmap B.
- * - Start handling events from the wayland compositor.
- *
- * Since both pixmap A and B will have scheduled wl_display_sync events to
- * indicate when their respective streams are connected, we will receive each
- * callback in the original order the pixmaps were created. This means the
- * following would happen:
- *
- * - Receive pixmap A's stream callback, attach its stream to the surface of
- * the window that just orphaned it.
- * - Receive pixmap B's stream callback, fall over and fail because the
- * window's surface now incorrectly has pixmap A's stream attached to it.
- *
- * We work around this problem by keeping a pending stream associated with
- * the xwl_pixmap, which itself is associated with the window pixmap.
- * In the scenario listed above, this should happen:
- *
- * - Begin processing X events...
- * - A window is resized, a new window pixmap is created causing us to
- * add an eglstream (known as eglstream A) waiting for its consumer
- * to finish attachment.
- * - Resize on same window happens. We invalidate the previously pending
- * stream on the old window pixmap.
- * A new window pixmap is attached to the window and another pending
- * stream is created for that new pixmap (known as eglstream B).
- * - Begin processing Wayland events...
- * - Receive invalidated callback from compositor for eglstream A, destroy
- * stream.
- * - Receive callback from compositor for eglstream B, create producer.
- * - Success!
- */
static void
xwl_eglstream_consumer_ready_callback(void *data,
struct wl_callback *callback,
uint32_t time)
{
- struct xwl_eglstream_pending_stream *pending = data;
- PixmapPtr pixmap = pending->pixmap;
+ PixmapPtr pixmap = data;
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
wl_callback_destroy(callback);
- pending->cb = NULL;
-
- if (!pending->is_valid) {
- xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
- dixDestroyPixmap(pixmap, 0);
- return;
- }
+ xwl_pixmap->pending_cb = NULL;
xwl_glamor_egl_make_current(xwl_screen);
@@ -541,42 +461,16 @@ xwl_eglstream_consumer_ready_callback(void *data,
ErrorF("eglstream: Failed to create EGLSurface for pixmap\n");
xwl_eglstream_print_error(xwl_screen->egl_display,
xwl_pixmap->stream, eglGetError());
- goto out;
+ } else {
+ DebugF("eglstream: completes eglstream for pixmap %p, congrats!\n",
+ pixmap);
}
-
- DebugF("eglstream: win %d completes eglstream for pixmap %p, congrats!\n",
- pending->window->drawable.id, pending->pixmap);
-
-out:
- xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
}
static const struct wl_callback_listener consumer_ready_listener = {
xwl_eglstream_consumer_ready_callback
};
-static struct xwl_eglstream_pending_stream *
-xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
-{
- struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
- struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
- struct xwl_eglstream_pending_stream *pending_stream;
-
- DebugF("eglstream: win %d queues new pending stream for pixmap %p\n",
- window->drawable.id, pixmap);
-
- pending_stream = calloc(1, sizeof(*pending_stream));
- pending_stream->window = window;
- pending_stream->pixmap = pixmap;
- pending_stream->is_valid = TRUE;
-
- pending_stream->cb = wl_display_sync(xwl_screen->display);
- wl_callback_add_listener(pending_stream->cb, &consumer_ready_listener,
- pending_stream);
-
- return pending_stream;
-}
-
static void
xwl_eglstream_buffer_release_callback(void *data)
{
@@ -656,9 +550,9 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
wl_eglstream_controller_attach_eglstream_consumer(
xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
- xwl_pixmap->pending_stream =
- xwl_eglstream_queue_pending_stream(window, pixmap);
-
+ xwl_pixmap->pending_cb = wl_display_sync(xwl_screen->display);
+ wl_callback_add_listener(xwl_pixmap->pending_cb, &consumer_ready_listener,
+ pixmap);
fail:
if (stream_fd >= 0)
close(stream_fd);
@@ -673,25 +567,22 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap) {
- struct xwl_eglstream_pending_stream *pending = xwl_pixmap->pending_stream;
-
- if (pending) {
+ if (xwl_pixmap->pending_cb) {
/* Wait for the compositor to finish connecting the consumer for
* this eglstream */
- assert(pending->is_valid);
-
return FALSE;
- } else {
- if (xwl_pixmap->surface != EGL_NO_SURFACE ||
- xwl_pixmap->type == XWL_PIXMAP_DMA_BUF)
- return TRUE;
-
- /* The pending stream got removed, we have a xwl_pixmap and
- * yet we do not have a surface.
- * So something went wrong with the surface creation, retry.
- */
- xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
}
+
+ if (xwl_pixmap->surface != EGL_NO_SURFACE ||
+ xwl_pixmap->type == XWL_PIXMAP_DMA_BUF) {
+ return TRUE;
+ }
+
+ /* The pending stream got removed, we have a xwl_pixmap and
+ * yet we do not have a surface.
+ * So something went wrong with the surface creation, retry.
+ */
+ xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
}
/* Glamor pixmap has no backing stream yet; begin making one and disallow
--
2.31.1

View File

@ -0,0 +1,88 @@
From a515f4f4336efb8a2adf9a3ac141129708297d80 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 29 Nov 2021 11:45:35 +0100
Subject: [PATCH xserver 2/4] xwayland/glamor: Change errors to verbose
messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On a normal startup sequence, the Xwayland glamor backend would log
an error whenever a required Wayland protocol is missing.
Those are not really errors though, more informational messages along
the glamor backend selection process.
Demote those errors to verbose messages to reduce the verbosity of
Xwayland at startup by default.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
(cherry picked from commit 30d0d4a19be61dd7b61f5ced992cb299e6a38068)
---
hw/xwayland/xwayland-glamor-eglstream.c | 6 ++++--
hw/xwayland/xwayland-glamor-gbm.c | 2 +-
hw/xwayland/xwayland-glamor.c | 6 ++++--
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 93d192d58..5a20b452f 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -753,12 +753,14 @@ xwl_glamor_eglstream_has_wl_interfaces(struct xwl_screen *xwl_screen)
xwl_eglstream_get(xwl_screen);
if (xwl_eglstream->display == NULL) {
- ErrorF("glamor: 'wl_eglstream_display' not supported\n");
+ LogMessageVerb(X_INFO, 3,
+ "glamor: 'wl_eglstream_display' not supported\n");
return FALSE;
}
if (xwl_eglstream->controller == NULL) {
- ErrorF("glamor: 'wl_eglstream_controller' not supported\n");
+ LogMessageVerb(X_INFO, 3,
+ "glamor: 'wl_eglstream_controller' not supported\n");
return FALSE;
}
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 466a1b052..e06b6f54b 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -835,7 +835,7 @@ xwl_glamor_gbm_has_wl_interfaces(struct xwl_screen *xwl_screen)
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
if (xwl_gbm->drm == NULL) {
- ErrorF("glamor: 'wl_drm' not supported\n");
+ LogMessageVerb(X_INFO, 3, "glamor: 'wl_drm' not supported\n");
return FALSE;
}
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index deb398f91..541d5e923 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -412,7 +412,8 @@ xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
return TRUE;
}
else
- ErrorF("Missing Wayland requirements for glamor GBM backend\n");
+ LogMessageVerb(X_INFO, 3,
+ "Missing Wayland requirements for glamor GBM backend\n");
#endif
return FALSE;
@@ -428,7 +429,8 @@ xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
return TRUE;
}
else
- ErrorF("Missing Wayland requirements for glamor EGLStream backend\n");
+ LogMessageVerb(X_INFO, 3,
+ "Missing Wayland requirements for glamor EGLStream backend\n");
#endif
return FALSE;
--
2.33.1

View File

@ -1,330 +0,0 @@
From ec91c17a881eaf69c4109f050e7bb9928906c52e Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Fri, 12 Feb 2021 12:09:27 -0800
Subject: [PATCH xserver 02/27] xwayland: move formats and modifiers functions
to common glamor code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is preliminary work for hardware accelerated rendering with the
NVIDIA driver.
This moves the modifiers and formats functions previously only available
to the GBM backend to the common glamor code so that it can be used by
both the GBM and EGLStream backends.
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
(cherry picked from commit 400d4d0fdd55192f394e1a8273dfb2423c895ec0)
---
hw/xwayland/xwayland-glamor-gbm.c | 115 ++----------------------------
hw/xwayland/xwayland-glamor.c | 111 ++++++++++++++++++++++++++++
hw/xwayland/xwayland-glamor.h | 8 ++-
3 files changed, 123 insertions(+), 111 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 73c69727e..455b755ca 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -97,25 +97,6 @@ gbm_format_for_depth(int depth)
}
}
-static uint32_t
-wl_drm_format_for_depth(int depth)
-{
- switch (depth) {
- case 15:
- return WL_DRM_FORMAT_XRGB1555;
- case 16:
- return WL_DRM_FORMAT_RGB565;
- case 24:
- return WL_DRM_FORMAT_XRGB8888;
- case 30:
- return WL_DRM_FORMAT_ARGB2101010;
- default:
- ErrorF("unexpected depth: %d\n", depth);
- case 32:
- return WL_DRM_FORMAT_ARGB8888;
- }
-}
-
static char
is_device_path_render_node (const char *device_path)
{
@@ -214,7 +195,7 @@ xwl_glamor_gbm_create_pixmap(ScreenPtr screen,
uint32_t num_modifiers;
uint64_t *modifiers = NULL;
- glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
+ xwl_glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
bo = gbm_bo_create_with_modifiers(xwl_gbm->gbm, width, height,
format, modifiers, num_modifiers);
free(modifiers);
@@ -277,8 +258,6 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
unsigned short width = pixmap->drawable.width;
unsigned short height = pixmap->drawable.height;
uint32_t format;
- struct xwl_format *xwl_format = NULL;
- Bool modifier_supported = FALSE;
int prime_fd;
int num_planes;
uint32_t strides[4];
@@ -317,23 +296,8 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
offsets[0] = 0;
#endif
- for (i = 0; i < xwl_screen->num_formats; i++) {
- if (xwl_screen->formats[i].format == format) {
- xwl_format = &xwl_screen->formats[i];
- break;
- }
- }
-
- if (xwl_format) {
- for (i = 0; i < xwl_format->num_modifiers; i++) {
- if (xwl_format->modifiers[i] == modifier) {
- modifier_supported = TRUE;
- break;
- }
- }
- }
-
- if (xwl_screen->dmabuf && modifier_supported) {
+ if (xwl_screen->dmabuf &&
+ xwl_glamor_is_modifier_supported(xwl_screen, format, modifier)) {
struct zwp_linux_buffer_params_v1 *params;
params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
@@ -592,83 +556,14 @@ glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
return -1;
}
-_X_EXPORT Bool
-glamor_get_formats(ScreenPtr screen,
- CARD32 *num_formats, CARD32 **formats)
-{
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
- int i;
-
- /* Explicitly zero the count as the caller may ignore the return value */
- *num_formats = 0;
-
- if (!xwl_gbm->dmabuf_capable || !xwl_screen->dmabuf)
- return FALSE;
-
- if (xwl_screen->num_formats == 0)
- return TRUE;
-
- *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
- if (*formats == NULL)
- return FALSE;
-
- for (i = 0; i < xwl_screen->num_formats; i++)
- (*formats)[i] = xwl_screen->formats[i].format;
- *num_formats = xwl_screen->num_formats;
-
- return TRUE;
-}
-
-_X_EXPORT Bool
-glamor_get_modifiers(ScreenPtr screen, uint32_t format,
- uint32_t *num_modifiers, uint64_t **modifiers)
-{
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
- struct xwl_format *xwl_format = NULL;
- int i;
-
- /* Explicitly zero the count as the caller may ignore the return value */
- *num_modifiers = 0;
-
- if (!xwl_gbm->dmabuf_capable || !xwl_screen->dmabuf)
- return FALSE;
-
- if (xwl_screen->num_formats == 0)
- return TRUE;
-
- for (i = 0; i < xwl_screen->num_formats; i++) {
- if (xwl_screen->formats[i].format == format) {
- xwl_format = &xwl_screen->formats[i];
- break;
- }
- }
-
- if (!xwl_format ||
- (xwl_format->num_modifiers == 1 &&
- xwl_format->modifiers[0] == DRM_FORMAT_MOD_INVALID))
- return FALSE;
-
- *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
- if (*modifiers == NULL)
- return FALSE;
-
- for (i = 0; i < xwl_format->num_modifiers; i++)
- (*modifiers)[i] = xwl_format->modifiers[i];
- *num_modifiers = xwl_format->num_modifiers;
-
- return TRUE;
-}
-
static const dri3_screen_info_rec xwl_dri3_info = {
.version = 2,
.open = NULL,
.pixmap_from_fds = glamor_pixmap_from_fds,
.fds_from_pixmap = glamor_fds_from_pixmap,
.open_client = xwl_dri3_open_client,
- .get_formats = glamor_get_formats,
- .get_modifiers = glamor_get_modifiers,
+ .get_formats = xwl_glamor_get_formats,
+ .get_modifiers = xwl_glamor_get_modifiers,
.get_drawable_modifiers = glamor_get_drawable_modifiers,
};
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index cce0c911e..d8bf1bd5d 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -79,6 +79,117 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
xwl_screen->glamor_ctx = glamor_ctx;
}
+Bool
+xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
+ uint32_t format, uint64_t modifier)
+{
+ struct xwl_format *xwl_format = NULL;
+ int i;
+
+ for (i = 0; i < xwl_screen->num_formats; i++) {
+ if (xwl_screen->formats[i].format == format) {
+ xwl_format = &xwl_screen->formats[i];
+ break;
+ }
+ }
+
+ if (xwl_format) {
+ for (i = 0; i < xwl_format->num_modifiers; i++) {
+ if (xwl_format->modifiers[i] == modifier) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+uint32_t
+wl_drm_format_for_depth(int depth)
+{
+ switch (depth) {
+ case 15:
+ return WL_DRM_FORMAT_XRGB1555;
+ case 16:
+ return WL_DRM_FORMAT_RGB565;
+ case 24:
+ return WL_DRM_FORMAT_XRGB8888;
+ case 30:
+ return WL_DRM_FORMAT_ARGB2101010;
+ default:
+ ErrorF("unexpected depth: %d\n", depth);
+ case 32:
+ return WL_DRM_FORMAT_ARGB8888;
+ }
+}
+
+Bool
+xwl_glamor_get_formats(ScreenPtr screen,
+ CARD32 *num_formats, CARD32 **formats)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ int i;
+
+ /* Explicitly zero the count as the caller may ignore the return value */
+ *num_formats = 0;
+
+ if (!xwl_screen->dmabuf)
+ return FALSE;
+
+ if (xwl_screen->num_formats == 0)
+ return TRUE;
+
+ *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
+ if (*formats == NULL)
+ return FALSE;
+
+ for (i = 0; i < xwl_screen->num_formats; i++)
+ (*formats)[i] = xwl_screen->formats[i].format;
+ *num_formats = xwl_screen->num_formats;
+
+ return TRUE;
+}
+
+Bool
+xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format,
+ uint32_t *num_modifiers, uint64_t **modifiers)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ struct xwl_format *xwl_format = NULL;
+ int i;
+
+ /* Explicitly zero the count as the caller may ignore the return value */
+ *num_modifiers = 0;
+
+ if (!xwl_screen->dmabuf)
+ return FALSE;
+
+ if (xwl_screen->num_formats == 0)
+ return TRUE;
+
+ for (i = 0; i < xwl_screen->num_formats; i++) {
+ if (xwl_screen->formats[i].format == format) {
+ xwl_format = &xwl_screen->formats[i];
+ break;
+ }
+ }
+
+ if (!xwl_format ||
+ (xwl_format->num_modifiers == 1 &&
+ xwl_format->modifiers[0] == DRM_FORMAT_MOD_INVALID))
+ return FALSE;
+
+ *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
+ if (*modifiers == NULL)
+ return FALSE;
+
+ for (i = 0; i < xwl_format->num_modifiers; i++)
+ (*modifiers)[i] = xwl_format->modifiers[i];
+ *num_modifiers = xwl_format->num_modifiers;
+
+ return TRUE;
+}
+
static void
xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
uint32_t format)
diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h
index e017fce80..1637a0733 100644
--- a/hw/xwayland/xwayland-glamor.h
+++ b/hw/xwayland/xwayland-glamor.h
@@ -120,7 +120,13 @@ void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen);
Bool xwl_glamor_has_present_flip(struct xwl_screen *xwl_screen);
Bool xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen);
Bool xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen);
-
+Bool xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
+ uint32_t format, uint64_t modifier);
+uint32_t wl_drm_format_for_depth(int depth);
+Bool xwl_glamor_get_formats(ScreenPtr screen,
+ CARD32 *num_formats, CARD32 **formats);
+Bool xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format,
+ uint32_t *num_modifiers, uint64_t **modifiers);
#ifdef XV
/* glamor Xv Adaptor */
--
2.31.1

View File

@ -0,0 +1,34 @@
From fe0c050276c09f43cc1ae80b4553db42398ca84c Mon Sep 17 00:00:00 2001
From: Povilas Kanapickas <povilas@radix.lt>
Date: Tue, 14 Dec 2021 15:00:02 +0200
Subject: [PATCH xserver 3/4] Xext: Fix out of bounds access in
SProcScreenSaverSuspend()
ZDI-CAN-14951, CVE-2021-4010
This vulnerability was discovered and the fix was suggested by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
(cherry picked from commit 6c4c53010772e3cb4cb8acd54950c8eec9c00d21)
---
Xext/saver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Xext/saver.c b/Xext/saver.c
index 1d7e3cadf..f813ba08d 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -1351,8 +1351,8 @@ SProcScreenSaverSuspend(ClientPtr client)
REQUEST(xScreenSaverSuspendReq);
swaps(&stuff->length);
- swapl(&stuff->suspend);
REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
+ swapl(&stuff->suspend);
return ProcScreenSaverSuspend(client);
}
--
2.33.1

View File

@ -0,0 +1,70 @@
From f9c435822c852659e3926502829f1b13ce6efc37 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 29 Nov 2022 13:26:57 +1000
Subject: [PATCH xserver 3/7] Xi: avoid integer truncation in length check of
ProcXIChangeProperty
This fixes an OOB read and the resulting information disclosure.
Length calculation for the request was clipped to a 32-bit integer. With
the correct stuff->num_items value the expected request size was
truncated, passing the REQUEST_FIXED_SIZE check.
The server then proceeded with reading at least stuff->num_items bytes
(depending on stuff->format) from the request and stuffing whatever it
finds into the property. In the process it would also allocate at least
stuff->num_items bytes, i.e. 4GB.
The same bug exists in ProcChangeProperty and ProcXChangeDeviceProperty,
so let's fix that too.
CVE-2022-46344, ZDI-CAN 19405
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
Xi/xiproperty.c | 4 ++--
dix/property.c | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c
index 68c362c628..066ba21fba 100644
--- a/Xi/xiproperty.c
+++ b/Xi/xiproperty.c
@@ -890,7 +890,7 @@ ProcXChangeDeviceProperty(ClientPtr client)
REQUEST(xChangeDevicePropertyReq);
DeviceIntPtr dev;
unsigned long len;
- int totalSize;
+ uint64_t totalSize;
int rc;
REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
@@ -1130,7 +1130,7 @@ ProcXIChangeProperty(ClientPtr client)
{
int rc;
DeviceIntPtr dev;
- int totalSize;
+ uint64_t totalSize;
unsigned long len;
REQUEST(xXIChangePropertyReq);
diff --git a/dix/property.c b/dix/property.c
index 94ef5a0ec0..acce94b2c6 100644
--- a/dix/property.c
+++ b/dix/property.c
@@ -205,7 +205,8 @@ ProcChangeProperty(ClientPtr client)
WindowPtr pWin;
char format, mode;
unsigned long len;
- int sizeInBytes, totalSize, err;
+ int sizeInBytes, err;
+ uint64_t totalSize;
REQUEST(xChangePropertyReq);
--
2.38.1

View File

@ -0,0 +1,219 @@
From ee5377d94ea587f584adbc9ab8372b3842cfa149 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 18 Dec 2023 12:26:20 +1000
Subject: [PATCH xserver 3/9] dix: fix DeviceStateNotify event calculation
The previous code only made sense if one considers buttons and keys to
be mutually exclusive on a device. That is not necessarily true, causing
a number of issues.
This function allocates and fills in the number of xEvents we need to
send the device state down the wire. This is split across multiple
32-byte devices including one deviceStateNotify event and optional
deviceKeyStateNotify, deviceButtonStateNotify and (possibly multiple)
deviceValuator events.
The previous behavior would instead compose a sequence
of [state, buttonstate, state, keystate, valuator...]. This is not
protocol correct, and on top of that made the code extremely convoluted.
Fix this by streamlining: add both button and key into the deviceStateNotify
and then append the key state and button state, followed by the
valuators. Finally, the deviceValuator events contain up to 6 valuators
per event but we only ever sent through 3 at a time. Let's double that
troughput.
CVE-2024-0229, ZDI-CAN-22678
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit 219c54b8a3337456ce5270ded6a67bcde53553d5)
---
dix/enterleave.c | 121 ++++++++++++++++++++---------------------------
1 file changed, 52 insertions(+), 69 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index 17964b00a..7b7ba1098 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -615,9 +615,15 @@ FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
ev->type = DeviceValuator;
ev->deviceid = dev->id;
- ev->num_valuators = nval < 3 ? nval : 3;
+ ev->num_valuators = nval < 6 ? nval : 6;
ev->first_valuator = first;
switch (ev->num_valuators) {
+ case 6:
+ ev->valuator2 = v->axisVal[first + 5];
+ case 5:
+ ev->valuator2 = v->axisVal[first + 4];
+ case 4:
+ ev->valuator2 = v->axisVal[first + 3];
case 3:
ev->valuator2 = v->axisVal[first + 2];
case 2:
@@ -626,7 +632,6 @@ FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
ev->valuator0 = v->axisVal[first];
break;
}
- first += ev->num_valuators;
}
static void
@@ -646,7 +651,7 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
ev->num_buttons = b->numButtons;
memcpy((char *) ev->buttons, (char *) b->down, 4);
}
- else if (k) {
+ if (k) {
ev->classes_reported |= (1 << KeyClass);
ev->num_keys = k->xkbInfo->desc->max_key_code -
k->xkbInfo->desc->min_key_code;
@@ -670,15 +675,26 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
}
}
-
+/**
+ * The device state notify event is split across multiple 32-byte events.
+ * The first one contains the first 32 button state bits, the first 32
+ * key state bits, and the first 3 valuator values.
+ *
+ * If a device has more than that, the server sends out:
+ * - one deviceButtonStateNotify for buttons 32 and above
+ * - one deviceKeyStateNotify for keys 32 and above
+ * - one deviceValuator event per 6 valuators above valuator 4
+ *
+ * All events but the last one have the deviceid binary ORed with MORE_EVENTS,
+ */
static void
DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
{
+ /* deviceStateNotify, deviceKeyStateNotify, deviceButtonStateNotify
+ * and one deviceValuator for each 6 valuators */
+ deviceStateNotify sev[3 + (MAX_VALUATORS + 6)/6];
int evcount = 1;
- deviceStateNotify sev[6 + (MAX_VALUATORS + 2)/3];
- deviceStateNotify *ev;
- deviceKeyStateNotify *kev;
- deviceButtonStateNotify *bev;
+ deviceStateNotify *ev = sev;
KeyClassPtr k;
ButtonClassPtr b;
@@ -691,82 +707,49 @@ DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
if ((b = dev->button) != NULL) {
nbuttons = b->numButtons;
- if (nbuttons > 32)
+ if (nbuttons > 32) /* first 32 are encoded in deviceStateNotify */
evcount++;
}
if ((k = dev->key) != NULL) {
nkeys = k->xkbInfo->desc->max_key_code - k->xkbInfo->desc->min_key_code;
- if (nkeys > 32)
+ if (nkeys > 32) /* first 32 are encoded in deviceStateNotify */
evcount++;
- if (nbuttons > 0) {
- evcount++;
- }
}
if ((v = dev->valuator) != NULL) {
nval = v->numAxes;
-
- if (nval > 3)
- evcount++;
- if (nval > 6) {
- if (!(k && b))
- evcount++;
- if (nval > 9)
- evcount += ((nval - 7) / 3);
- }
+ /* first three are encoded in deviceStateNotify, then
+ * it's 6 per deviceValuator event */
+ evcount += ((nval - 3) + 6)/6;
}
- ev = sev;
- FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
-
- if (b != NULL) {
- FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
- first += 3;
- nval -= 3;
- if (nbuttons > 32) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- bev = (deviceButtonStateNotify *) ev++;
- bev->type = DeviceButtonStateNotify;
- bev->deviceid = dev->id;
- memcpy((char *) &bev->buttons[4], (char *) &b->down[4],
- DOWN_LENGTH - 4);
- }
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
+ BUG_RETURN(evcount <= ARRAY_SIZE(sev));
+
+ FixDeviceStateNotify(dev, ev, k, b, v, first);
+
+ if (b != NULL && nbuttons > 32) {
+ deviceButtonStateNotify *bev = (deviceButtonStateNotify *) ++ev;
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ bev->type = DeviceButtonStateNotify;
+ bev->deviceid = dev->id;
+ memcpy((char *) &bev->buttons[4], (char *) &b->down[4],
+ DOWN_LENGTH - 4);
}
- if (k != NULL) {
- FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
- first += 3;
- nval -= 3;
- if (nkeys > 32) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- kev = (deviceKeyStateNotify *) ev++;
- kev->type = DeviceKeyStateNotify;
- kev->deviceid = dev->id;
- memmove((char *) &kev->keys[0], (char *) &k->down[4], 28);
- }
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
+ if (k != NULL && nkeys > 32) {
+ deviceKeyStateNotify *kev = (deviceKeyStateNotify *) ++ev;
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ kev->type = DeviceKeyStateNotify;
+ kev->deviceid = dev->id;
+ memmove((char *) &kev->keys[0], (char *) &k->down[4], 28);
}
+ first = 3;
+ nval -= 3;
while (nval > 0) {
- FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
- first += 3;
- nval -= 3;
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
+ ev->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ++ev, v, first);
+ first += 6;
+ nval -= 6;
}
DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
--
2.43.0

View File

@ -0,0 +1,183 @@
From bd134231e282d9eb126b6fdaa40bb383180fa72b Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 5 Jul 2022 11:11:06 +1000
Subject: [PATCH xserver 3/3] xkb: add request length validation for
XkbSetGeometry
No validation of the various fields on that report were done, so a
malicious client could send a short request that claims it had N
sections, or rows, or keys, and the server would process the request for
N sections, running out of bounds of the actual request data.
Fix this by adding size checks to ensure our data is valid.
ZDI-CAN 16062, CVE-2022-2319.
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 6907b6ea2b4ce949cb07271f5b678d5966d9df42)
---
xkb/xkb.c | 43 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 36464a770..27d19793e 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5160,7 +5160,7 @@ _GetCountedString(char **wire_inout, ClientPtr client, char **str)
}
static Status
-_CheckSetDoodad(char **wire_inout,
+_CheckSetDoodad(char **wire_inout, xkbSetGeometryReq *req,
XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
{
char *wire;
@@ -5171,6 +5171,9 @@ _CheckSetDoodad(char **wire_inout,
Status status;
dWire = (xkbDoodadWireDesc *) (*wire_inout);
+ if (!_XkbCheckRequestBounds(client, req, dWire, dWire + 1))
+ return BadLength;
+
any = dWire->any;
wire = (char *) &dWire[1];
if (client->swapped) {
@@ -5273,7 +5276,7 @@ _CheckSetDoodad(char **wire_inout,
}
static Status
-_CheckSetOverlay(char **wire_inout,
+_CheckSetOverlay(char **wire_inout, xkbSetGeometryReq *req,
XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
{
register int r;
@@ -5284,6 +5287,9 @@ _CheckSetOverlay(char **wire_inout,
wire = *wire_inout;
olWire = (xkbOverlayWireDesc *) wire;
+ if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1))
+ return BadLength;
+
if (client->swapped) {
swapl(&olWire->name);
}
@@ -5295,6 +5301,9 @@ _CheckSetOverlay(char **wire_inout,
xkbOverlayKeyWireDesc *kWire;
XkbOverlayRowPtr row;
+ if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1))
+ return BadLength;
+
if (rWire->rowUnder > section->num_rows) {
client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
rWire->rowUnder);
@@ -5303,6 +5312,9 @@ _CheckSetOverlay(char **wire_inout,
row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
for (k = 0; k < rWire->nKeys; k++, kWire++) {
+ if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1))
+ return BadLength;
+
if (XkbAddGeomOverlayKey(ol, row,
(char *) kWire->over,
(char *) kWire->under) == NULL) {
@@ -5336,6 +5348,9 @@ _CheckSetSections(XkbGeometryPtr geom,
register int r;
xkbRowWireDesc *rWire;
+ if (!_XkbCheckRequestBounds(client, req, sWire, sWire + 1))
+ return BadLength;
+
if (client->swapped) {
swapl(&sWire->name);
swaps(&sWire->top);
@@ -5361,6 +5376,9 @@ _CheckSetSections(XkbGeometryPtr geom,
XkbRowPtr row;
xkbKeyWireDesc *kWire;
+ if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1))
+ return BadLength;
+
if (client->swapped) {
swaps(&rWire->top);
swaps(&rWire->left);
@@ -5375,6 +5393,9 @@ _CheckSetSections(XkbGeometryPtr geom,
for (k = 0; k < rWire->nKeys; k++, kWire++) {
XkbKeyPtr key;
+ if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1))
+ return BadLength;
+
key = XkbAddGeomKey(row);
if (!key)
return BadAlloc;
@@ -5400,7 +5421,7 @@ _CheckSetSections(XkbGeometryPtr geom,
register int d;
for (d = 0; d < sWire->nDoodads; d++) {
- status = _CheckSetDoodad(&wire, geom, section, client);
+ status = _CheckSetDoodad(&wire, req, geom, section, client);
if (status != Success)
return status;
}
@@ -5409,7 +5430,7 @@ _CheckSetSections(XkbGeometryPtr geom,
register int o;
for (o = 0; o < sWire->nOverlays; o++) {
- status = _CheckSetOverlay(&wire, geom, section, client);
+ status = _CheckSetOverlay(&wire, req, geom, section, client);
if (status != Success)
return status;
}
@@ -5443,6 +5464,9 @@ _CheckSetShapes(XkbGeometryPtr geom,
xkbOutlineWireDesc *olWire;
XkbOutlinePtr ol;
+ if (!_XkbCheckRequestBounds(client, req, shapeWire, shapeWire + 1))
+ return BadLength;
+
shape =
XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
if (!shape)
@@ -5453,12 +5477,18 @@ _CheckSetShapes(XkbGeometryPtr geom,
XkbPointPtr pt;
xkbPointWireDesc *ptWire;
+ if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1))
+ return BadLength;
+
ol = XkbAddGeomOutline(shape, olWire->nPoints);
if (!ol)
return BadAlloc;
ol->corner_radius = olWire->cornerRadius;
ptWire = (xkbPointWireDesc *) &olWire[1];
for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++, ptWire++) {
+ if (!_XkbCheckRequestBounds(client, req, ptWire, ptWire + 1))
+ return BadLength;
+
pt->x = ptWire->x;
pt->y = ptWire->y;
if (client->swapped) {
@@ -5564,12 +5594,15 @@ _CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
return status;
for (i = 0; i < req->nDoodads; i++) {
- status = _CheckSetDoodad(&wire, geom, NULL, client);
+ status = _CheckSetDoodad(&wire, req, geom, NULL, client);
if (status != Success)
return status;
}
for (i = 0; i < req->nKeyAliases; i++) {
+ if (!_XkbCheckRequestBounds(client, req, wire, wire + XkbKeyNameLength))
+ return BadLength;
+
if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
return BadAlloc;
wire += 2 * XkbKeyNameLength;
--
2.36.1

View File

@ -1,112 +0,0 @@
From c42d3e8edc85856f95c971d5fbc5d59011c23cdc Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Wed, 3 Mar 2021 11:56:41 +0100
Subject: [PATCH xserver 03/27] xwayland: Add check_flip() glamor backend
function
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is preliminary work for hardware accelerated rendering with the
NVIDIA driver.
This exposes a new glamor backend function, check_flip, which can be
used to control whether flipping is supported for the given pixmap.
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
(cherry picked from commit bc99dd2127f12f1aae55971c09a2792eeaa98444)
---
hw/xwayland/xwayland-glamor-eglstream.c | 7 +++++++
hw/xwayland/xwayland-glamor-gbm.c | 1 +
hw/xwayland/xwayland-glamor.c | 11 +++++++++++
hw/xwayland/xwayland-glamor.h | 6 ++++++
4 files changed, 25 insertions(+)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 9b2c2c43f..ccaa59cbe 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -633,6 +633,12 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
pixmap->refcnt++;
}
+static Bool
+xwl_glamor_eglstream_check_flip(PixmapPtr pixmap)
+{
+ return FALSE;
+}
+
static void
xwl_eglstream_display_handle_caps(void *data,
struct wl_eglstream_display *disp,
@@ -942,6 +948,7 @@ xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
xwl_screen->eglstream_backend.get_wl_buffer_for_pixmap = xwl_glamor_eglstream_get_wl_buffer_for_pixmap;
xwl_screen->eglstream_backend.post_damage = xwl_glamor_eglstream_post_damage;
xwl_screen->eglstream_backend.allow_commits = xwl_glamor_eglstream_allow_commits;
+ xwl_screen->eglstream_backend.check_flip = xwl_glamor_eglstream_check_flip;
xwl_screen->eglstream_backend.is_available = TRUE;
xwl_screen->eglstream_backend.backend_flags = XWL_EGL_BACKEND_NO_FLAG;
}
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 455b755ca..1b1d517da 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -967,6 +967,7 @@ xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
xwl_screen->gbm_backend.init_egl = xwl_glamor_gbm_init_egl;
xwl_screen->gbm_backend.init_screen = xwl_glamor_gbm_init_screen;
xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
+ xwl_screen->gbm_backend.check_flip = NULL;
xwl_screen->gbm_backend.is_available = TRUE;
xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_HAS_PRESENT_FLIP |
XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH |
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index d8bf1bd5d..060471f01 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -79,6 +79,17 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
xwl_screen->glamor_ctx = glamor_ctx;
}
+Bool
+xwl_glamor_check_flip(PixmapPtr pixmap)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+
+ if (xwl_screen->egl_backend->check_flip)
+ return xwl_screen->egl_backend->check_flip(pixmap);
+
+ return TRUE;
+}
+
Bool
xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
uint32_t format, uint64_t modifier)
diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h
index 1637a0733..a86b30b40 100644
--- a/hw/xwayland/xwayland-glamor.h
+++ b/hw/xwayland/xwayland-glamor.h
@@ -92,6 +92,11 @@ struct xwl_egl_backend {
* callback is optional.
*/
Bool (*allow_commits)(struct xwl_window *xwl_window);
+
+ /* Called by Xwayland to check whether the given pixmap can be
+ * presented by xwl_present_flip. If not implemented, assumed TRUE.
+ */
+ Bool (*check_flip)(PixmapPtr pixmap);
};
#ifdef XWL_HAS_GLAMOR
@@ -127,6 +132,7 @@ Bool xwl_glamor_get_formats(ScreenPtr screen,
CARD32 *num_formats, CARD32 **formats);
Bool xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format,
uint32_t *num_modifiers, uint64_t **modifiers);
+Bool xwl_glamor_check_flip(PixmapPtr pixmap);
#ifdef XV
/* glamor Xv Adaptor */
--
2.31.1

View File

@ -0,0 +1,42 @@
From 3206e133cb768709d32f260ac4b1bb17a46141a7 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 17 Nov 2021 13:09:58 +0100
Subject: [PATCH xserver 3/4] xwayland/glamor: Log backend selected for debug
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add (verbose) statements to trace the actual backend used with glamor.
That can be useful for debugging.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit c5d1fed9fa32244739677ec5c58ea87b261e023b)
---
hw/xwayland/xwayland-glamor.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 541d5e923..b34eafabb 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -409,6 +409,7 @@ xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
if (xwl_screen->gbm_backend.is_available &&
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->gbm_backend)) {
xwl_screen->egl_backend = &xwl_screen->gbm_backend;
+ LogMessageVerb(X_INFO, 3, "glamor: Using GBM backend\n");
return TRUE;
}
else
@@ -426,6 +427,7 @@ xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
if (xwl_screen->eglstream_backend.is_available &&
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
+ LogMessageVerb(X_INFO, 3, "glamor: Using EGLStream backend\n");
return TRUE;
}
else
--
2.33.1

View File

@ -0,0 +1,64 @@
From 0dab0b527ac5c4fe0272ea679522bd87238a733b Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 29 Nov 2022 13:55:32 +1000
Subject: [PATCH xserver 4/7] Xi: disallow passive grabs with a detail > 255
The XKB protocol effectively prevents us from ever using keycodes above
255. For buttons it's theoretically possible but realistically too niche
to worry about. For all other passive grabs, the detail must be zero
anyway.
This fixes an OOB write:
ProcXIPassiveUngrabDevice() calls DeletePassiveGrabFromList with a
temporary grab struct which contains tempGrab->detail.exact = stuff->detail.
For matching existing grabs, DeleteDetailFromMask is called with the
stuff->detail value. This function creates a new mask with the one bit
representing stuff->detail cleared.
However, the array size for the new mask is 8 * sizeof(CARD32) bits,
thus any detail above 255 results in an OOB array write.
CVE-2022-46341, ZDI-CAN 19381
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
Xi/xipassivegrab.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index 65d5870f6f..89a591098a 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -133,6 +133,12 @@ ProcXIPassiveGrabDevice(ClientPtr client)
return BadValue;
}
+ /* XI2 allows 32-bit keycodes but thanks to XKB we can never
+ * implement this. Just return an error for all keycodes that
+ * cannot work anyway, same for buttons > 255. */
+ if (stuff->detail > 255)
+ return XIAlreadyGrabbed;
+
if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1],
stuff->mask_len * 4) != Success)
return BadValue;
@@ -313,6 +319,12 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
return BadValue;
}
+ /* We don't allow passive grabs for details > 255 anyway */
+ if (stuff->detail > 255) {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
if (rc != Success)
return rc;
--
2.38.1

View File

@ -0,0 +1,39 @@
From 1c22e4a35e71d98a082ad2f8f7bc778a8859e18d Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Thu, 21 Dec 2023 13:48:10 +1000
Subject: [PATCH xserver 4/9] Xi: when creating a new ButtonClass, set the
number of buttons
There's a racy sequence where a master device may copy the button class
from the slave, without ever initializing numButtons. This leads to a
device with zero buttons but a button class which is invalid.
Let's copy the numButtons value from the source - by definition if we
don't have a button class yet we do not have any other slave devices
with more than this number of buttons anyway.
CVE-2024-0229, ZDI-CAN-22678
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit df3c65706eb169d5938df0052059f3e0d5981b74)
---
Xi/exevents.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 54ea11a93..e16171468 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -605,6 +605,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
to->button = calloc(1, sizeof(ButtonClassRec));
if (!to->button)
FatalError("[Xi] no memory for class shift.\n");
+ to->button->numButtons = from->button->numButtons;
}
else
classes->button = NULL;
--
2.43.0

View File

@ -0,0 +1,53 @@
From 59c977bff66de77bd93ce8853e33e1b4ca661a49 Mon Sep 17 00:00:00 2001
From: Povilas Kanapickas <povilas@radix.lt>
Date: Tue, 14 Dec 2021 15:00:03 +0200
Subject: [PATCH xserver 4/4] render: Fix out of bounds access in
SProcRenderCompositeGlyphs()
ZDI-CAN-14192, CVE-2021-4008
This vulnerability was discovered and the fix was suggested by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
(cherry picked from commit ebce7e2d80e7c80e1dda60f2f0bc886f1106ba60)
---
render/render.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/render/render.c b/render/render.c
index c376090ca..456f156d4 100644
--- a/render/render.c
+++ b/render/render.c
@@ -2309,6 +2309,9 @@ SProcRenderCompositeGlyphs(ClientPtr client)
i = elt->len;
if (i == 0xff) {
+ if (buffer + 4 > end) {
+ return BadLength;
+ }
swapl((int *) buffer);
buffer += 4;
}
@@ -2319,12 +2322,18 @@ SProcRenderCompositeGlyphs(ClientPtr client)
buffer += i;
break;
case 2:
+ if (buffer + i * 2 > end) {
+ return BadLength;
+ }
while (i--) {
swaps((short *) buffer);
buffer += 2;
}
break;
case 4:
+ if (buffer + i * 4 > end) {
+ return BadLength;
+ }
while (i--) {
swapl((int *) buffer);
buffer += 4;
--
2.33.1

View File

@ -0,0 +1,64 @@
From bdc00ba749ac6cde35c025f5f6b1a5b49c1f4960 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 17 Nov 2021 09:56:52 +0100
Subject: [PATCH xserver 4/4] xwayland/eglstream: Prefer EGLstream if available
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Currently, when given the choice, Xwayland will pick the GBM backend
over the EGLstream backend if both are available, unless the command
line option “-eglstream” is specified.
The NVIDIA proprietary driver had no support for GBM until driver series
495, but starting with the driver series 495, both can be used.
But there are other requirements with the rest of the stack, typically
Mesa, egl-wayland, libglvnd as documented in the NVIDIA driver.
So if the NVIDIA driver series 495 gets installed, Xwayland will pick
the GBM backend even if EGLstream is available and may fail to render
properly.
To avoid that issue, prefer EGLstream if EGLstream and all the Wayland
interfaces are available, and fallback to GBM automatically unless
“-eglstream” was specified.
With this, the compositor, given the choice, can decide which actual
backend Xwayland would use by advertising (or not) the Wayland
"wl_eglstream_controller" interface.
This change has no impact on compositors which do not have support for
EGLstream in the first place.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 6dd9709bd85cf5de4067887818c864220b951355)
---
hw/xwayland/xwayland-glamor.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index b34eafabb..f46b677f5 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -441,14 +441,10 @@ xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
void
xwl_glamor_select_backend(struct xwl_screen *xwl_screen, Bool use_eglstream)
{
- if (use_eglstream) {
- if (!xwl_glamor_select_eglstream_backend(xwl_screen))
+ if (!xwl_glamor_select_eglstream_backend(xwl_screen)) {
+ if (!use_eglstream)
xwl_glamor_select_gbm_backend(xwl_screen);
}
- else {
- if (!xwl_glamor_select_gbm_backend(xwl_screen))
- xwl_glamor_select_eglstream_backend(xwl_screen);
- }
}
Bool
--
2.33.1

View File

@ -1,425 +0,0 @@
From 6d1529b8d6b3e7c8bf758b670e2122a6af4d5346 Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Thu, 3 Dec 2020 14:57:51 -0800
Subject: [PATCH xserver 04/27] xwayland: implement pixmap_from_buffers for the
eglstream backend
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Provides an implementation for the pixmap_from_buffers DRI3 function for
xwayland's eglstream backend. This will be used by the NVIDIA GLX driver
to pass buffers from client applications to the server. These can then
be presented using the PRESENT extension.
To hopefully make this less error-prone, we also introduce a "type"
field for this struct to distinguish between xwl_pixmaps for the new
DRI3-created pixmaps and those for the existing glamor-created pixmaps.
Additionally, the patch enables wnmd present mode with the eglstream backend.
This involves creating a wl_buffer for the provided dma-buf before importing it
into EGL and passing this to the compositor so it can be scanned out directly
if possible.
Since both backends now support this present mode, the HAS_PRESENT_FLIP flag is
no longer needed, so it can be removed.
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
(cherry picked from commit 38e875904b039ec1889e7c81eb1d577a4f69b26d)
---
hw/xwayland/xwayland-glamor-eglstream.c | 202 +++++++++++++++++++++++-
hw/xwayland/xwayland-glamor-gbm.c | 3 +-
hw/xwayland/xwayland-glamor.c | 12 --
hw/xwayland/xwayland-glamor.h | 6 +-
hw/xwayland/xwayland-present.c | 5 +-
5 files changed, 204 insertions(+), 24 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index ccaa59cbe..2d8380e1f 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -37,6 +37,8 @@
#include <glamor_transfer.h>
#include <xf86drm.h>
+#include <dri3.h>
+#include <drm_fourcc.h>
#include <epoxy/egl.h>
@@ -47,6 +49,7 @@
#include "wayland-eglstream-client-protocol.h"
#include "wayland-eglstream-controller-client-protocol.h"
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
struct xwl_eglstream_pending_stream {
PixmapPtr pixmap;
@@ -80,12 +83,23 @@ struct xwl_eglstream_private {
GLuint blit_is_rgba_pos;
};
+enum xwl_pixmap_type {
+ XWL_PIXMAP_EGLSTREAM, /* Pixmaps created by glamor. */
+ XWL_PIXMAP_DMA_BUF, /* Pixmaps allocated through DRI3. */
+};
+
struct xwl_pixmap {
- struct wl_buffer *buffer;
+ enum xwl_pixmap_type type;
+ /* add any new <= 4-byte member here to avoid holes on 64-bit */
struct xwl_screen *xwl_screen;
+ struct wl_buffer *buffer;
+ /* XWL_PIXMAP_EGLSTREAM. */
EGLStreamKHR stream;
EGLSurface surface;
+
+ /* XWL_PIXMAP_DMA_BUF. */
+ EGLImage image;
};
static DevPrivateKeyRec xwl_eglstream_private_key;
@@ -289,12 +303,18 @@ xwl_eglstream_unref_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
xwl_screen->egl_context);
}
- if (xwl_pixmap->surface)
+ if (xwl_pixmap->surface != EGL_NO_SURFACE)
eglDestroySurface(xwl_screen->egl_display, xwl_pixmap->surface);
- eglDestroyStreamKHR(xwl_screen->egl_display, xwl_pixmap->stream);
+ if (xwl_pixmap->stream != EGL_NO_STREAM_KHR)
+ eglDestroyStreamKHR(xwl_screen->egl_display, xwl_pixmap->stream);
+
+ if (xwl_pixmap->buffer)
+ wl_buffer_destroy(xwl_pixmap->buffer);
+
+ if (xwl_pixmap->image != EGL_NO_IMAGE_KHR)
+ eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
- wl_buffer_destroy(xwl_pixmap->buffer);
free(xwl_pixmap);
}
@@ -509,9 +529,13 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
FatalError("Not enough memory to create pixmap\n");
xwl_pixmap_set_private(pixmap, xwl_pixmap);
+ xwl_pixmap->type = XWL_PIXMAP_EGLSTREAM;
+ xwl_pixmap->image = EGL_NO_IMAGE;
+
xwl_glamor_egl_make_current(xwl_screen);
xwl_pixmap->xwl_screen = xwl_screen;
+ xwl_pixmap->surface = EGL_NO_SURFACE;
xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
stream_fd = eglGetStreamFileDescriptorKHR(xwl_screen->egl_display,
xwl_pixmap->stream);
@@ -552,6 +576,7 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap) {
+ assert(xwl_pixmap->type == XWL_PIXMAP_EGLSTREAM);
if (pending) {
/* Wait for the compositor to finish connecting the consumer for
* this eglstream */
@@ -590,6 +615,8 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
};
GLint saved_vao;
+ assert(xwl_pixmap->type == XWL_PIXMAP_EGLSTREAM);
+
/* Unbind the framebuffer BEFORE binding the EGLSurface, otherwise we
* won't actually draw to it
*/
@@ -636,7 +663,7 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
static Bool
xwl_glamor_eglstream_check_flip(PixmapPtr pixmap)
{
- return FALSE;
+ return xwl_pixmap_get(pixmap)->type == XWL_PIXMAP_DMA_BUF;
}
static void
@@ -681,6 +708,9 @@ xwl_glamor_eglstream_init_wl_registry(struct xwl_screen *xwl_screen,
xwl_eglstream->controller = wl_registry_bind(
wl_registry, id, &wl_eglstream_controller_interface, version);
return TRUE;
+ } else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0) {
+ xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
+ return TRUE;
}
/* no match */
@@ -779,6 +809,163 @@ xwl_eglstream_init_shaders(struct xwl_screen *xwl_screen)
glGetUniformLocation(xwl_eglstream->blit_prog, "is_rgba");
}
+static int
+xwl_dri3_open_client(ClientPtr client,
+ ScreenPtr screen,
+ RRProviderPtr provider,
+ int *pfd)
+{
+ /* Not supported with this backend. */
+ return BadImplementation;
+}
+
+static PixmapPtr
+xwl_dri3_pixmap_from_fds(ScreenPtr screen,
+ CARD8 num_fds, const int *fds,
+ CARD16 width, CARD16 height,
+ const CARD32 *strides, const CARD32 *offsets,
+ CARD8 depth, CARD8 bpp,
+ uint64_t modifier)
+{
+ PixmapPtr pixmap;
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ struct xwl_pixmap *xwl_pixmap;
+ unsigned int texture;
+ EGLint image_attribs[48];
+ uint32_t mod_hi = modifier >> 32, mod_lo = modifier & 0xffffffff, format;
+ int attrib = 0, i;
+ struct zwp_linux_buffer_params_v1 *params;
+
+ format = wl_drm_format_for_depth(depth);
+ if (!xwl_glamor_is_modifier_supported(xwl_screen, format, modifier)) {
+ ErrorF("glamor: unsupported format modifier\n");
+ return NULL;
+ }
+
+ xwl_pixmap = calloc(1, sizeof (*xwl_pixmap));
+ if (!xwl_pixmap)
+ return NULL;
+ xwl_pixmap->type = XWL_PIXMAP_DMA_BUF;
+ xwl_pixmap->xwl_screen = xwl_screen;
+
+ xwl_pixmap->buffer = NULL;
+ xwl_pixmap->stream = EGL_NO_STREAM_KHR;
+ xwl_pixmap->surface = EGL_NO_SURFACE;
+
+ params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
+ for (i = 0; i < num_fds; i++) {
+ zwp_linux_buffer_params_v1_add(params, fds[i], i,
+ offsets[i], strides[i],
+ mod_hi, mod_lo);
+ }
+ xwl_pixmap->buffer =
+ zwp_linux_buffer_params_v1_create_immed(params, width, height,
+ format, 0);
+ zwp_linux_buffer_params_v1_destroy(params);
+
+
+ image_attribs[attrib++] = EGL_WIDTH;
+ image_attribs[attrib++] = width;
+ image_attribs[attrib++] = EGL_HEIGHT;
+ image_attribs[attrib++] = height;
+ image_attribs[attrib++] = EGL_LINUX_DRM_FOURCC_EXT;
+ image_attribs[attrib++] = drm_format_for_depth(depth, bpp);
+
+ if (num_fds > 0) {
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_FD_EXT;
+ image_attribs[attrib++] = fds[0];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
+ image_attribs[attrib++] = offsets[0];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
+ image_attribs[attrib++] = strides[0];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
+ image_attribs[attrib++] = mod_hi;
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
+ image_attribs[attrib++] = mod_lo;
+ }
+ if (num_fds > 1) {
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_FD_EXT;
+ image_attribs[attrib++] = fds[1];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
+ image_attribs[attrib++] = offsets[1];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
+ image_attribs[attrib++] = strides[1];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
+ image_attribs[attrib++] = mod_hi;
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
+ image_attribs[attrib++] = mod_lo;
+ }
+ if (num_fds > 2) {
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_FD_EXT;
+ image_attribs[attrib++] = fds[2];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
+ image_attribs[attrib++] = offsets[2];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
+ image_attribs[attrib++] = strides[2];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
+ image_attribs[attrib++] = mod_hi;
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
+ image_attribs[attrib++] = mod_lo;
+ }
+ if (num_fds > 3) {
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_FD_EXT;
+ image_attribs[attrib++] = fds[3];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
+ image_attribs[attrib++] = offsets[3];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
+ image_attribs[attrib++] = strides[3];
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
+ image_attribs[attrib++] = mod_hi;
+ image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
+ image_attribs[attrib++] = mod_lo;
+ }
+ image_attribs[attrib++] = EGL_NONE;
+
+ xwl_glamor_egl_make_current(xwl_screen);
+
+ /* eglCreateImageKHR will close fds */
+ xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
+ EGL_NO_CONTEXT,
+ EGL_LINUX_DMA_BUF_EXT,
+ NULL, image_attribs);
+ if (xwl_pixmap->image == EGL_NO_IMAGE_KHR) {
+ ErrorF("eglCreateImageKHR failed!\n");
+ if (xwl_pixmap->buffer)
+ wl_buffer_destroy(xwl_pixmap->buffer);
+ free(xwl_pixmap);
+ return NULL;
+ }
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ pixmap = glamor_create_pixmap(screen, width, height, depth,
+ GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
+ glamor_set_pixmap_texture(pixmap, texture);
+ glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+ wl_buffer_add_listener(xwl_pixmap->buffer,
+ &xwl_eglstream_buffer_release_listener,
+ pixmap);
+ xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+ return pixmap;
+}
+
+static const dri3_screen_info_rec xwl_dri3_info = {
+ .version = 2,
+ .open = NULL,
+ .pixmap_from_fds = xwl_dri3_pixmap_from_fds,
+ .fds_from_pixmap = NULL,
+ .open_client = xwl_dri3_open_client,
+ .get_formats = xwl_glamor_get_formats,
+ .get_modifiers = xwl_glamor_get_modifiers,
+ .get_drawable_modifiers = glamor_get_drawable_modifiers,
+};
+
static Bool
xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
{
@@ -858,6 +1045,11 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
xwl_eglstream_init_shaders(xwl_screen);
+ if (epoxy_has_gl_extension("GL_OES_EGL_image") &&
+ !dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
+ ErrorF("DRI3 initialization failed. Performance will be affected.\n");
+ }
+
return TRUE;
error:
xwl_eglstream_cleanup(xwl_screen);
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 1b1d517da..12d820e44 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -969,7 +969,6 @@ xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
xwl_screen->gbm_backend.check_flip = NULL;
xwl_screen->gbm_backend.is_available = TRUE;
- xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_HAS_PRESENT_FLIP |
- XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH |
+ xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH |
XWL_EGL_BACKEND_NEEDS_N_BUFFERING;
}
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 060471f01..9e44d5106 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -362,16 +362,6 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
return 0;
}
-Bool
-xwl_glamor_has_present_flip(struct xwl_screen *xwl_screen)
-{
- if (!xwl_screen->glamor || !xwl_screen->egl_backend)
- return FALSE;
-
- return (xwl_screen->egl_backend->backend_flags &
- XWL_EGL_BACKEND_HAS_PRESENT_FLIP);
-}
-
Bool
xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen)
{
@@ -430,8 +420,6 @@ xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
#ifdef XWL_HAS_EGLSTREAM
if (xwl_screen->eglstream_backend.is_available &&
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
- ErrorF("glamor: Using nvidia's EGLStream interface, direct rendering impossible.\n");
- ErrorF("glamor: Performance may be affected. Ask your vendor to support GBM!\n");
xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
return TRUE;
}
diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h
index a86b30b40..26ab78f04 100644
--- a/hw/xwayland/xwayland-glamor.h
+++ b/hw/xwayland/xwayland-glamor.h
@@ -34,9 +34,8 @@
typedef enum _xwl_egl_backend_flags {
XWL_EGL_BACKEND_NO_FLAG = 0,
- XWL_EGL_BACKEND_HAS_PRESENT_FLIP = (1 << 0),
- XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH = (1 << 1),
- XWL_EGL_BACKEND_NEEDS_N_BUFFERING = (1 << 2),
+ XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH = (1 << 0),
+ XWL_EGL_BACKEND_NEEDS_N_BUFFERING = (1 << 1),
} xwl_egl_backend_flags;
struct xwl_egl_backend {
@@ -122,7 +121,6 @@ void xwl_glamor_post_damage(struct xwl_window *xwl_window,
PixmapPtr pixmap, RegionPtr region);
Bool xwl_glamor_allow_commits(struct xwl_window *xwl_window);
void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen);
-Bool xwl_glamor_has_present_flip(struct xwl_screen *xwl_screen);
Bool xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen);
Bool xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen);
Bool xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 666ea15e7..7ba7efc11 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -404,6 +404,9 @@ xwl_present_check_flip2(RRCrtcPtr crtc,
if (!xwl_window)
return FALSE;
+ if (!xwl_glamor_check_flip(pixmap))
+ return FALSE;
+
/* Can't flip if the window pixmap doesn't match the xwl_window parent
* window's, e.g. because a client redirected this window or one of its
* parents.
@@ -540,7 +543,7 @@ xwl_present_init(ScreenPtr screen)
{
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- if (!xwl_glamor_has_present_flip(xwl_screen))
+ if (!xwl_screen->glamor || !xwl_screen->egl_backend)
return FALSE;
if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0))
--
2.31.1

View File

@ -0,0 +1,47 @@
From 94f6fe99d87cf6ba0adadd95c595158c345b7d29 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 29 Nov 2022 14:53:07 +1000
Subject: [PATCH xserver 5/7] Xext: free the screen saver resource when
replacing it
This fixes a use-after-free bug:
When a client first calls ScreenSaverSetAttributes(), a struct
ScreenSaverAttrRec is allocated and added to the client's
resources.
When the same client calls ScreenSaverSetAttributes() again, a new
struct ScreenSaverAttrRec is allocated, replacing the old struct. The
old struct was freed but not removed from the clients resources.
Later, when the client is destroyed the resource system invokes
ScreenSaverFreeAttr and attempts to clean up the already freed struct.
Fix this by letting the resource system free the old attrs instead.
CVE-2022-46343, ZDI-CAN 19404
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
Xext/saver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Xext/saver.c b/Xext/saver.c
index f813ba08d1..fd6153c313 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -1051,7 +1051,7 @@ ScreenSaverSetAttributes(ClientPtr client)
pVlist++;
}
if (pPriv->attr)
- FreeScreenAttr(pPriv->attr);
+ FreeResource(pPriv->attr->resource, AttrType);
pPriv->attr = pAttr;
pAttr->resource = FakeClientID(client->index);
if (!AddResource(pAttr->resource, AttrType, (void *) pAttr))
--
2.38.1

View File

@ -0,0 +1,111 @@
From 7efd09cdb13ae1a4100f68a11947afe581fa1ee8 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Thu, 4 Jan 2024 10:01:24 +1000
Subject: [PATCH xserver 5/9] Xi: flush hierarchy events after adding/removing
master devices
The `XISendDeviceHierarchyEvent()` function allocates space to store up
to `MAXDEVICES` (256) `xXIHierarchyInfo` structures in `info`.
If a device with a given ID was removed and a new device with the same
ID added both in the same operation, the single device ID will lead to
two info structures being written to `info`.
Since this case can occur for every device ID at once, a total of two
times `MAXDEVICES` info structures might be written to the allocation.
To avoid it, once one add/remove master is processed, send out the
device hierarchy event for the current state and continue. That event
thus only ever has exactly one of either added/removed in it (and
optionally slave attached/detached).
CVE-2024-21885, ZDI-CAN-22744
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit 4a5e9b1895627d40d26045bd0b7ef3dce503cbd1)
---
Xi/xichangehierarchy.c | 27 ++++++++++++++++++++++-----
1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
index d2d985848..72d00451e 100644
--- a/Xi/xichangehierarchy.c
+++ b/Xi/xichangehierarchy.c
@@ -416,6 +416,11 @@ ProcXIChangeHierarchy(ClientPtr client)
size_t len; /* length of data remaining in request */
int rc = Success;
int flags[MAXDEVICES] = { 0 };
+ enum {
+ NO_CHANGE,
+ FLUSH,
+ CHANGED,
+ } changes = NO_CHANGE;
REQUEST(xXIChangeHierarchyReq);
REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq);
@@ -465,8 +470,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = add_master(client, c, flags);
if (rc != Success)
goto unwind;
- }
+ changes = FLUSH;
break;
+ }
case XIRemoveMaster:
{
xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any;
@@ -475,8 +481,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = remove_master(client, r, flags);
if (rc != Success)
goto unwind;
- }
+ changes = FLUSH;
break;
+ }
case XIDetachSlave:
{
xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any;
@@ -485,8 +492,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = detach_slave(client, c, flags);
if (rc != Success)
goto unwind;
- }
+ changes = CHANGED;
break;
+ }
case XIAttachSlave:
{
xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any;
@@ -495,16 +503,25 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = attach_slave(client, c, flags);
if (rc != Success)
goto unwind;
+ changes = CHANGED;
+ break;
}
+ default:
break;
}
+ if (changes == FLUSH) {
+ XISendDeviceHierarchyEvent(flags);
+ memset(flags, 0, sizeof(flags));
+ changes = NO_CHANGE;
+ }
+
len -= any->length * 4;
any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4);
}
unwind:
-
- XISendDeviceHierarchyEvent(flags);
+ if (changes != NO_CHANGE)
+ XISendDeviceHierarchyEvent(flags);
return rc;
}
--
2.43.0

View File

@ -1,61 +0,0 @@
From 43d1648dc71d01628a6a65a62364c1a3994a88a8 Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Tue, 27 Apr 2021 07:23:44 -0400
Subject: [PATCH xserver 05/27] xwayland-eglstream: fix X11 rendering to
flipping GL / VK window
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If a window is being used for direct rendering with OpenGL or Vulkan, and is
using the flipping path for presentation, it's pixmap will be set to a dma-buf
backed pixmap created by the client-side GL driver. However, this means that
xwl_glamor_eglstream_post_damage won't work since it requires that the pixmap
has an EGLSurface that it can render to, which dma-buf backed pixmaps do not.
In this case, though, xwl_glamor_eglstream_post_damage is not necessary since
glamor will have rendered directly to the pixmap, so we can simply pass it
directly to the compositor. There's no need for the intermediate copy we
normally do in that function.
Therefore, this change adds an early-return case to post_damage for dma-buf
backed pixmaps, and removes the corresponding asserts from that function and
allow_commits.
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 4f6fbd5009ae533cf0b3bbe382502254f9276a01)
---
hw/xwayland/xwayland-glamor-eglstream.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 2d8380e1f..17295f3bd 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -576,7 +576,6 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap) {
- assert(xwl_pixmap->type == XWL_PIXMAP_EGLSTREAM);
if (pending) {
/* Wait for the compositor to finish connecting the consumer for
* this eglstream */
@@ -615,7 +614,12 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
};
GLint saved_vao;
- assert(xwl_pixmap->type == XWL_PIXMAP_EGLSTREAM);
+ if (xwl_pixmap->type != XWL_PIXMAP_EGLSTREAM)
+ /* This can happen if a client does X11 rendering on a
+ * flipping OpenGL or Vulkan window. In that case, we don't
+ * need to do the copy below.
+ */
+ return;
/* Unbind the framebuffer BEFORE binding the EGLSurface, otherwise we
* won't actually draw to it
--
2.31.1

View File

@ -0,0 +1,73 @@
From a42635ee3c01f71a49052d83a372933504c9db04 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Wed, 30 Nov 2022 11:20:40 +1000
Subject: [PATCH xserver 6/7] Xext: free the XvRTVideoNotify when turning off
from the same client
This fixes a use-after-free bug:
When a client first calls XvdiSelectVideoNotify() on a drawable with a
TRUE onoff argument, a struct XvVideoNotifyRec is allocated. This struct
is added twice to the resources:
- as the drawable's XvRTVideoNotifyList. This happens only once per
drawable, subsequent calls append to this list.
- as the client's XvRTVideoNotify. This happens for every client.
The struct keeps the ClientPtr around once it has been added for a
client. The idea, presumably, is that if the client disconnects we can remove
all structs from the drawable's list that match the client (by resetting
the ClientPtr to NULL), but if the drawable is destroyed we can remove
and free the whole list.
However, if the same client then calls XvdiSelectVideoNotify() on the
same drawable with a FALSE onoff argument, only the ClientPtr on the
existing struct was set to NULL. The struct itself remained in the
client's resources.
If the drawable is now destroyed, the resource system invokes
XvdiDestroyVideoNotifyList which frees the whole list for this drawable
- including our struct. This function however does not free the resource
for the client since our ClientPtr is NULL.
Later, when the client is destroyed and the resource system invokes
XvdiDestroyVideoNotify, we unconditionally set the ClientPtr to NULL. On
a struct that has been freed previously. This is generally frowned upon.
Fix this by calling FreeResource() on the second call instead of merely
setting the ClientPtr to NULL. This removes the struct from the client
resources (but not from the list), ensuring that it won't be accessed
again when the client quits.
Note that the assignment tpn->client = NULL; is superfluous since the
XvdiDestroyVideoNotify function will do this anyway. But it's left for
clarity and to match a similar invocation in XvdiSelectPortNotify.
CVE-2022-46342, ZDI-CAN 19400
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
Xext/xvmain.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Xext/xvmain.c b/Xext/xvmain.c
index f627471938..2a08f8744a 100644
--- a/Xext/xvmain.c
+++ b/Xext/xvmain.c
@@ -811,8 +811,10 @@ XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
tpn = pn;
while (tpn) {
if (tpn->client == client) {
- if (!onoff)
+ if (!onoff) {
tpn->client = NULL;
+ FreeResource(tpn->id, XvRTVideoNotify);
+ }
return Success;
}
if (!tpn->client)
--
2.38.1

View File

@ -0,0 +1,73 @@
From 01cd3a72858ccc1afb0b42ace92263f2912619a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jexposit@redhat.com>
Date: Fri, 22 Dec 2023 18:28:31 +0100
Subject: [PATCH xserver 6/9] Xi: do not keep linked list pointer during
recursion
The `DisableDevice()` function is called whenever an enabled device
is disabled and it moves the device from the `inputInfo.devices` linked
list to the `inputInfo.off_devices` linked list.
However, its link/unlink operation has an issue during the recursive
call to `DisableDevice()` due to the `prev` pointer pointing to a
removed device.
This issue leads to a length mismatch between the total number of
devices and the number of device in the list, leading to a heap
overflow and, possibly, to local privilege escalation.
Simplify the code that checked whether the device passed to
`DisableDevice()` was in `inputInfo.devices` or not and find the
previous device after the recursion.
CVE-2024-21886, ZDI-CAN-22840
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
(cherry picked from commit bc1fdbe46559dd947674375946bbef54dd0ce36b)
---
dix/devices.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/dix/devices.c b/dix/devices.c
index 8fe4a341c..f3db37203 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -453,14 +453,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
{
DeviceIntPtr *prev, other;
BOOL enabled;
+ BOOL dev_in_devices_list = FALSE;
int flags[MAXDEVICES] = { 0 };
if (!dev->enabled)
return TRUE;
- for (prev = &inputInfo.devices;
- *prev && (*prev != dev); prev = &(*prev)->next);
- if (*prev != dev)
+ for (other = inputInfo.devices; other; other = other->next) {
+ if (other == dev) {
+ dev_in_devices_list = TRUE;
+ break;
+ }
+ }
+
+ if (!dev_in_devices_list)
return FALSE;
TouchEndPhysicallyActiveTouches(dev);
@@ -511,6 +517,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
LeaveWindow(dev);
SetFocusOut(dev);
+ for (prev = &inputInfo.devices;
+ *prev && (*prev != dev); prev = &(*prev)->next);
+
*prev = dev->next;
dev->next = inputInfo.off_devices;
inputInfo.off_devices = dev;
--
2.43.0

View File

@ -1,53 +0,0 @@
From 95224f0f92bc516983038a6326fba041cdef6e75 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 29 Mar 2021 14:22:56 +0200
Subject: [PATCH xserver 06/27] xwayland/eglstream: Check buffer creation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
EGLStream wl_eglstream_display_create_stream() may fail, yet Xwayland
would try to attach the buffer which may cause a fatal Wayland protocol
error raised by the compositor.
Check if the buffer creation worked, and fail gracefully otherwise (like
wayland-eglsurface does).
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Martin Peres <martin.peres@mupuf.org>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit 4f0889e98306d30a37aba0fadb1fd3790c13205a)
---
hw/xwayland/xwayland-glamor-eglstream.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 17295f3bd..c6e17bf8b 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -548,6 +548,10 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
stream_fd,
WL_EGLSTREAM_HANDLE_TYPE_FD,
&stream_attribs);
+ if (!xwl_pixmap->buffer) {
+ ErrorF("eglstream: Failed to create buffer\n");
+ goto fail;
+ }
wl_buffer_add_listener(xwl_pixmap->buffer,
&xwl_eglstream_buffer_release_listener,
@@ -562,7 +566,9 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
xwl_eglstream_queue_pending_stream(xwl_screen, window, pixmap);
- close(stream_fd);
+fail:
+ if (stream_fd >= 0)
+ close(stream_fd);
}
static Bool
--
2.31.1

View File

@ -0,0 +1,55 @@
From 42f8d1828b4fc1e0b8165a767a0b74edcdbf3806 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Fri, 5 Jan 2024 09:40:27 +1000
Subject: [PATCH xserver 7/9] dix: when disabling a master, float disabled
slaved devices too
Disabling a master device floats all slave devices but we didn't do this
to already-disabled slave devices. As a result those devices kept their
reference to the master device resulting in access to already freed
memory if the master device was removed before the corresponding slave
device.
And to match this behavior, also forcibly reset that pointer during
CloseDownDevices().
Related to CVE-2024-21886, ZDI-CAN-22840
(cherry picked from commit 26769aa71fcbe0a8403b7fb13b7c9010cc07c3a8)
---
dix/devices.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/dix/devices.c b/dix/devices.c
index f3db37203..95190b5b7 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -483,6 +483,13 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
flags[other->id] |= XISlaveDetached;
}
}
+
+ for (other = inputInfo.off_devices; other; other = other->next) {
+ if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) {
+ AttachDevice(NULL, other, NULL);
+ flags[other->id] |= XISlaveDetached;
+ }
+ }
}
else {
for (other = inputInfo.devices; other; other = other->next) {
@@ -1080,6 +1087,11 @@ CloseDownDevices(void)
dev->master = NULL;
}
+ for (dev = inputInfo.off_devices; dev; dev = dev->next) {
+ if (!IsMaster(dev) && !IsFloating(dev))
+ dev->master = NULL;
+ }
+
CloseDeviceList(&inputInfo.devices);
CloseDeviceList(&inputInfo.off_devices);
--
2.43.0

View File

@ -0,0 +1,35 @@
From 774260dbae1fa505cd2848c786baed9a8db5179d Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 5 Dec 2022 15:55:54 +1000
Subject: [PATCH xserver 7/7] xkb: reset the radio_groups pointer to NULL after
freeing it
Unlike other elements of the keymap, this pointer was freed but not
reset. On a subsequent XkbGetKbdByName request, the server may access
already freed memory.
CVE-2022-46283, ZDI-CAN-19530
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
---
xkb/xkbUtils.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index dd089c2046..3f5791a183 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -1326,6 +1326,7 @@ _XkbCopyNames(XkbDescPtr src, XkbDescPtr dst)
}
else {
free(dst->names->radio_groups);
+ dst->names->radio_groups = NULL;
}
dst->names->num_rg = src->names->num_rg;
--
2.38.1

View File

@ -1,88 +0,0 @@
From 8a07b3e391bbed0b7d8f2ed37928b362eec3beee Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 29 Mar 2021 15:01:15 +0200
Subject: [PATCH xserver 07/27] xwayland: Check buffer prior to attaching it
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If the buffer is NULL, do not even try to attach it, and risk a Wayland
protocol error which would be fatal to us.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Martin Peres <martin.peres@mupuf.org>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit 25d2f4948f0abd39e099b8ac69b7cb1dab38a10a)
---
hw/xwayland/xwayland-cursor.c | 11 +++++++++--
hw/xwayland/xwayland-present.c | 7 ++++++-
hw/xwayland/xwayland-window.c | 5 +++++
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index fac8840e6..c4457cc2a 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -162,8 +162,15 @@ static void
xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
struct xwl_cursor *xwl_cursor, PixmapPtr pixmap)
{
- wl_surface_attach(xwl_cursor->surface,
- xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
+ struct wl_buffer *buffer;
+
+ buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+ if (!buffer) {
+ ErrorF("cursor: Error getting buffer\n");
+ return;
+ }
+
+ wl_surface_attach(xwl_cursor->surface, buffer, 0, 0);
xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
xwl_seat->x_cursor->bits->width,
xwl_seat->x_cursor->bits->height);
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 7ba7efc11..83d67517a 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -443,6 +443,12 @@ xwl_present_flip(WindowPtr present_window,
if (!xwl_window)
return FALSE;
+ buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
+ if (!buffer) {
+ ErrorF("present: Error getting buffer\n");
+ return FALSE;
+ }
+
damage_box = RegionExtents(damage);
event = malloc(sizeof *event);
@@ -450,7 +456,6 @@ xwl_present_flip(WindowPtr present_window,
return FALSE;
pixmap->refcnt++;
- buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
event->event_id = event_id;
event->xwl_present_window = xwl_present_window;
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index d0c7c581d..af4290ec7 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -805,6 +805,11 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
#endif
buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+ if (!buffer) {
+ ErrorF("Error getting buffer\n");
+ return;
+ }
+
#ifdef XWL_HAS_GLAMOR
if (xwl_screen->glamor)
xwl_glamor_post_damage(xwl_window, pixmap, region);
--
2.31.1

View File

@ -0,0 +1,35 @@
From bb1711b7fba42f2a0c7d1c09beee241a1b2bcc30 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 19 Dec 2022 10:06:45 +1000
Subject: [PATCH xserver] Xext: fix invalid event type mask in
XTestSwapFakeInput
In commit b320ca0 the mask was inadvertently changed from octal 0177 to
hexadecimal 0x177.
Fixes commit b320ca0ffe4c0c872eeb3a93d9bde21f765c7c63
Xtest: disallow GenericEvents in XTestSwapFakeInput
Found by Stuart Cassoff
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
Xext/xtest.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 2985a4ce6e..dde5c4cf9d 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -502,7 +502,7 @@ XTestSwapFakeInput(ClientPtr client, xReq * req)
nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) {
- int evtype = ev->u.u.type & 0x177;
+ int evtype = ev->u.u.type & 0177;
/* Swap event */
proc = EventSwapVector[evtype];
/* no swapping proc; invalid event type? */
--
2.38.1

View File

@ -1,38 +0,0 @@
From 85638273f23338d06776cdb7bb422440f690038a Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Tue, 30 Mar 2021 08:48:25 +0200
Subject: [PATCH xserver 08/27] glamor: Dump backtrace on GL error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Currrently, when a GL error is triggered, glamor would log the error
which may not be sufficient to trace it back to the cause of the error.
Also dump the backtrace which may give more information as to where the
error comes from.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Martin Peres <martin.peres@mupuf.org>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit 3b265c59a6456f6e4abfb9e1694237bc56f1776a)
---
glamor/glamor.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 3baef4b9f..b8406f42d 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -414,6 +414,7 @@ glamor_debug_output_callback(GLenum source,
LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n",
screen->myNum, length, message);
+ xorg_backtrace();
}
/**
--
2.31.1

View File

@ -0,0 +1,61 @@
From 4093057b98bc5a178f130c9ba6b0b28385e24ae5 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 6 Dec 2023 12:09:41 +0100
Subject: [PATCH xserver 8/9] glx: Call XACE hooks on the GLX buffer
The XSELINUX code will label resources at creation by checking the
access mode. When the access mode is DixCreateAccess, it will call the
function to label the new resource SELinuxLabelResource().
However, GLX buffers do not go through the XACE hooks when created,
hence leaving the resource actually unlabeled.
When, later, the client tries to create another resource using that
drawable (like a GC for example), the XSELINUX code would try to use
the security ID of that object which has never been labeled, get a NULL
pointer and crash when checking whether the requested permissions are
granted for subject security ID.
To avoid the issue, make sure to call the XACE hooks when creating the
GLX buffers.
Credit goes to Donn Seeley <donn@xmission.com> for providing the patch.
CVE-2024-0408
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit e5e8586a12a3ec915673edffa10dc8fe5e15dac3)
---
glx/glxcmds.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index fc26a2e34..1e46d0c72 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -48,6 +48,7 @@
#include "indirect_util.h"
#include "protocol-versions.h"
#include "glxvndabi.h"
+#include "xace.h"
static char GLXServerVendorName[] = "SGI";
@@ -1392,6 +1393,13 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
if (!pPixmap)
return BadAlloc;
+ err = XaceHook(XACE_RESOURCE_ACCESS, client, glxDrawableId, RT_PIXMAP,
+ pPixmap, RT_NONE, NULL, DixCreateAccess);
+ if (err != Success) {
+ (*pGlxScreen->pScreen->DestroyPixmap) (pPixmap);
+ return err;
+ }
+
/* Assign the pixmap the same id as the pbuffer and add it as a
* resource so it and the DRI2 drawable will be reclaimed when the
* pbuffer is destroyed. */
--
2.43.0

View File

@ -0,0 +1,44 @@
From 51be9e767a02cdc6a524dc895dcc81abb689d50b Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 6 Dec 2023 11:51:56 +0100
Subject: [PATCH xserver 9/9] ephyr,xwayland: Use the proper private key for
cursor
The cursor in DIX is actually split in two parts, the cursor itself and
the cursor bits, each with their own devPrivates.
The cursor itself includes the cursor bits, meaning that the cursor bits
devPrivates in within structure of the cursor.
Both Xephyr and Xwayland were using the private key for the cursor bits
to store the data for the cursor, and when using XSELINUX which comes
with its own special devPrivates, the data stored in that cursor bits'
devPrivates would interfere with the XSELINUX devPrivates data and the
SELINUX security ID would point to some other unrelated data, causing a
crash in the XSELINUX code when trying to (re)use the security ID.
CVE-2024-0409
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 2ef0f1116c65d5cb06d7b6d83f8a1aea702c94f7)
---
hw/xwayland/xwayland-cursor.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index e3c1aaa50..bd94b0cfb 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -431,7 +431,7 @@ static miPointerScreenFuncRec xwl_pointer_screen_funcs = {
Bool
xwl_screen_init_cursor(struct xwl_screen *xwl_screen)
{
- if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0))
+ if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR, 0))
return FALSE;
return miPointerInitialize(xwl_screen->screen,
--
2.43.0

View File

@ -1,125 +0,0 @@
From c28bb0e879775aec83f5554522724eee592685dc Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 31 Mar 2021 13:57:45 +0200
Subject: [PATCH xserver 09/27] xwayland/glamor: Add return status to
post_damage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If the glamor backend failed to post damage, the caller should do the
same to avoid a failure to attach the buffer to the Wayland surface.
Change the API of Xwayland's glamor backend post_damage() to return a
status so that xwl_window_post_damage() can tell whether the callee
failed.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit 252cbad316f43edc08aa5c844789398a58ba270c)
---
hw/xwayland/xwayland-glamor-eglstream.c | 6 ++++--
hw/xwayland/xwayland-glamor.c | 6 ++++--
hw/xwayland/xwayland-glamor.h | 4 ++--
hw/xwayland/xwayland-window.c | 8 ++++++--
4 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index c6e17bf8b..f64d05064 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -605,7 +605,7 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
return FALSE;
}
-static void
+static Bool
xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
PixmapPtr pixmap, RegionPtr region)
{
@@ -625,7 +625,7 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
* flipping OpenGL or Vulkan window. In that case, we don't
* need to do the copy below.
*/
- return;
+ return TRUE;
/* Unbind the framebuffer BEFORE binding the EGLSurface, otherwise we
* won't actually draw to it
@@ -668,6 +668,8 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
/* hang onto the pixmap until the compositor has released it */
pixmap->refcnt++;
+
+ return TRUE;
}
static Bool
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 9e44d5106..e940f9fd7 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -304,14 +304,16 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
return NULL;
}
-void
+Bool
xwl_glamor_post_damage(struct xwl_window *xwl_window,
PixmapPtr pixmap, RegionPtr region)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
if (xwl_screen->egl_backend->post_damage)
- xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
+ return xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
+
+ return TRUE;
}
Bool
diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h
index 26ab78f04..cf3c4fba3 100644
--- a/hw/xwayland/xwayland-glamor.h
+++ b/hw/xwayland/xwayland-glamor.h
@@ -83,7 +83,7 @@ struct xwl_egl_backend {
* you should implement blitting from the glamor pixmap to the wayland
* pixmap here. Otherwise, this callback is optional.
*/
- void (*post_damage)(struct xwl_window *xwl_window,
+ Bool (*post_damage)(struct xwl_window *xwl_window,
PixmapPtr pixmap, RegionPtr region);
/* Called by Xwayland to confirm with the egl backend that the given
@@ -117,7 +117,7 @@ void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
uint32_t version);
Bool xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen,
struct xwl_egl_backend *xwl_egl_backend);
-void xwl_glamor_post_damage(struct xwl_window *xwl_window,
+Bool xwl_glamor_post_damage(struct xwl_window *xwl_window,
PixmapPtr pixmap, RegionPtr region);
Bool xwl_glamor_allow_commits(struct xwl_window *xwl_window);
void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen);
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index af4290ec7..00f161eda 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -811,8 +811,12 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
}
#ifdef XWL_HAS_GLAMOR
- if (xwl_screen->glamor)
- xwl_glamor_post_damage(xwl_window, pixmap, region);
+ if (xwl_screen->glamor) {
+ if (!xwl_glamor_post_damage(xwl_window, pixmap, region)) {
+ ErrorF("glamor: Failed to post damage\n");
+ return;
+ }
+ }
#endif
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
--
2.31.1

View File

@ -1,74 +0,0 @@
From 070abe64b15db831802a842aa1965403eb24679e Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 31 Mar 2021 09:49:35 +0200
Subject: [PATCH xserver 10/27] xwayland/eglstream: Check framebuffer status
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The EGLStream backend would sometime generate GL errors trying to draw
to the framebuffer, which gives an invalid buffer, which in turn would
generate a Wayland error from the compositor which is fatal to the
client.
Check the framebuffer status and bail out early if it's not complete,
to avoid getting into trouble later.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit 85244d2a2081d61a2e4a06e847041f638de01e3f)
---
hw/xwayland/xwayland-glamor-eglstream.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index f64d05064..64fe93b7c 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -619,6 +619,7 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
box->x2 - box->x1, box->y2 - box->y1
};
GLint saved_vao;
+ int status;
if (xwl_pixmap->type != XWL_PIXMAP_EGLSTREAM)
/* This can happen if a client does X11 rendering on a
@@ -652,6 +653,13 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
glUniform1i(xwl_eglstream->blit_is_rgba_pos,
pixmap->drawable.depth >= 32);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ ErrorF("eglstream: Framebuffer incomplete 0x%X, not posting damage\n", status);
+ status = FALSE;
+ goto out;
+ }
+
/* Blit rendered image into EGLStream surface */
glDrawBuffer(GL_BACK);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -662,14 +670,16 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
else
eglSwapBuffers(xwl_screen->egl_display, xwl_pixmap->surface);
+ /* hang onto the pixmap until the compositor has released it */
+ pixmap->refcnt++;
+ status = TRUE;
+
+out:
/* Restore previous state */
glBindVertexArray(saved_vao);
glBindTexture(GL_TEXTURE_2D, 0);
- /* hang onto the pixmap until the compositor has released it */
- pixmap->refcnt++;
-
- return TRUE;
+ return status;
}
static Bool
--
2.31.1

View File

@ -1,138 +0,0 @@
From 9966356963803db35997f26330fb1245777012a1 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Thu, 15 Apr 2021 10:59:36 +0200
Subject: [PATCH xserver 11/27] xwayland/eglstream: Small refactoring
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some functions are called "callback" whereas they are not longer
callback functions or "unref" while they no longer deal with a reference
counter anymore, which is quite confusing. Rename those functions to be
more explicit.
Also, the pending streams can be destroyed in different places, move the
common code to separate function to avoid duplicating code and help with
readability of the code.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 823f3254fabd16e5e721da57cd260beac9b8f8bd)
---
hw/xwayland/xwayland-glamor-eglstream.c | 42 ++++++++++++++-----------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 64fe93b7c..9abb7b779 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -287,7 +287,7 @@ xwl_glamor_egl_device_has_egl_extensions(void *device,
}
static void
-xwl_eglstream_unref_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
+xwl_eglstream_destroy_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
{
struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
@@ -319,7 +319,17 @@ xwl_eglstream_unref_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
}
static void
-xwl_glamor_eglstream_del_pending_stream_cb(struct xwl_pixmap *xwl_pixmap)
+xwl_glamor_eglstream_destroy_pending_stream(struct xwl_eglstream_pending_stream *pending)
+{
+ if (pending->cb)
+ wl_callback_destroy(pending->cb);
+ xwl_eglstream_window_set_pending(pending->window, NULL);
+ xorg_list_del(&pending->link);
+ free(pending);
+}
+
+static void
+xwl_glamor_eglstream_remove_pending_stream(struct xwl_pixmap *xwl_pixmap)
{
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_pixmap->xwl_screen);
@@ -328,10 +338,7 @@ xwl_glamor_eglstream_del_pending_stream_cb(struct xwl_pixmap *xwl_pixmap)
xorg_list_for_each_entry(pending,
&xwl_eglstream->pending_streams, link) {
if (pending->xwl_pixmap == xwl_pixmap) {
- wl_callback_destroy(pending->cb);
- xwl_eglstream_window_set_pending(pending->window, NULL);
- xorg_list_del(&pending->link);
- free(pending);
+ xwl_glamor_eglstream_destroy_pending_stream(pending);
break;
}
}
@@ -343,9 +350,9 @@ xwl_glamor_eglstream_destroy_pixmap(PixmapPtr pixmap)
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap && pixmap->refcnt == 1) {
- xwl_glamor_eglstream_del_pending_stream_cb(xwl_pixmap);
+ xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
+ xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
xwl_pixmap_del_buffer_release_cb(pixmap);
- xwl_eglstream_unref_pixmap_stream(xwl_pixmap);
}
return glamor_destroy_pixmap(pixmap);
}
@@ -432,8 +439,6 @@ xwl_eglstream_consumer_ready_callback(void *data,
struct xwl_eglstream_pending_stream *pending;
Bool found = FALSE;
- wl_callback_destroy(callback);
-
xorg_list_for_each_entry(pending, &xwl_eglstream->pending_streams, link) {
if (pending->cb == callback) {
found = TRUE;
@@ -442,8 +447,11 @@ xwl_eglstream_consumer_ready_callback(void *data,
}
assert(found);
+ wl_callback_destroy(callback);
+ pending->cb = NULL;
+
if (!pending->is_valid) {
- xwl_eglstream_unref_pixmap_stream(pending->xwl_pixmap);
+ xwl_eglstream_destroy_pixmap_stream(pending->xwl_pixmap);
goto out;
}
@@ -462,9 +470,7 @@ xwl_eglstream_consumer_ready_callback(void *data,
pending->window->drawable.id, pending->pixmap);
out:
- xwl_eglstream_window_set_pending(pending->window, NULL);
- xorg_list_del(&pending->link);
- free(pending);
+ xwl_glamor_eglstream_destroy_pending_stream(pending);
}
static const struct wl_callback_listener consumer_ready_listener = {
@@ -514,8 +520,8 @@ static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
};
static void
-xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
- WindowPtr window, PixmapPtr pixmap)
+xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
+ WindowPtr window, PixmapPtr pixmap)
{
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
@@ -599,8 +605,8 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
/* Glamor pixmap has no backing stream yet; begin making one and disallow
* commits until then
*/
- xwl_eglstream_create_pending_stream(xwl_screen, xwl_window->window,
- pixmap);
+ xwl_eglstream_create_pixmap_and_stream(xwl_screen, xwl_window->window,
+ pixmap);
return FALSE;
}
--
2.31.1

View File

@ -1,150 +0,0 @@
From e8f7568016249822bb95c87447ded6abb724c13b Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Thu, 1 Apr 2021 08:46:52 +0200
Subject: [PATCH xserver 12/27] xwayland/eglstream: Add more error checking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
eglCreateStreamKHR() can fail and return EGL_NO_STREAM_KHR, in which
case there is no point in trying to create a buffer from it.
Similarly, eglCreateStreamProducerSurfaceKHR() also fail and return
EGL_NO_SURFACE, which in turn will be used in eglMakeCurrent() as
draw/read surface, and therefore would mean no draw/read buffer.
In those cases, log the error, and bail out early. That won't solve the
issue but will help with investigating the root cause of issues with
EGLStream backend.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit cc596bcfb273eeab82ac3d59867668af8bad2abf)
---
hw/xwayland/xwayland-glamor-eglstream.c | 93 +++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 9abb7b779..77b24a4b4 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -387,6 +387,84 @@ xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
xwl_screen->screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
}
+static const char *
+xwl_eglstream_get_error_str(EGLint error)
+{
+ switch (error) {
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_STATE_KHR:
+ return "EGL_BAD_STATE_KHR";
+ case EGL_BAD_STREAM_KHR:
+ return "EGL_BAD_STREAM_KHR";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ default:
+ return "Unknown error";
+ }
+}
+
+static const char *
+xwl_eglstream_get_stream_state_str(EGLint state)
+{
+ switch (state) {
+ case EGL_STREAM_STATE_CREATED_KHR:
+ return "EGL_STREAM_STATE_CREATED_KHR";
+ case EGL_STREAM_STATE_CONNECTING_KHR:
+ return "EGL_STREAM_STATE_CONNECTING_KHR";
+ case EGL_STREAM_STATE_EMPTY_KHR:
+ return "EGL_STREAM_STATE_EMPTY_KHR";
+ case EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR:
+ return "EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR";
+ case EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR:
+ return "EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR";
+ case EGL_STREAM_STATE_DISCONNECTED_KHR:
+ return "EGL_STREAM_STATE_DISCONNECTED_KHR";
+ default:
+ return "Unknown state";
+ }
+}
+
+static EGLint
+xwl_eglstream_get_state(EGLDisplay egl_display, EGLStreamKHR egl_stream)
+{
+ EGLint state;
+
+ eglQueryStreamKHR(egl_display, egl_stream, EGL_STREAM_STATE_KHR, &state);
+ if (!eglQueryStreamKHR(egl_display, egl_stream,
+ EGL_STREAM_STATE_KHR, &state)) {
+ EGLint state_error = eglGetError();
+ ErrorF("eglstream: Failed to query state - error 0x%X: %s\n",
+ state_error, xwl_eglstream_get_error_str(state_error));
+ return EGL_FALSE;
+ }
+
+ return state;
+}
+
+
+static void
+xwl_eglstream_print_error(EGLDisplay egl_display,
+ EGLStreamKHR egl_stream, EGLint error)
+{
+ ErrorF("eglstream: error 0x%X: %s\n", error,
+ xwl_eglstream_get_error_str(error));
+
+ if (error == EGL_BAD_STATE_KHR) {
+ EGLint state = xwl_eglstream_get_state(egl_display, egl_stream);
+ ErrorF("eglstream: stream state 0x%X: %s\n", state,
+ xwl_eglstream_get_stream_state_str(state));
+ }
+}
+
/* Because we run asynchronously with our wayland compositor, it's possible
* that an X client event could cause us to begin creating a stream for a
* pixmap/window combo before the stream for the pixmap this window
@@ -466,6 +544,13 @@ xwl_eglstream_consumer_ready_callback(void *data,
EGL_NONE
});
+ if (xwl_pixmap->surface == EGL_NO_SURFACE) {
+ ErrorF("eglstream: Failed to create EGLSurface for pixmap\n");
+ xwl_eglstream_print_error(xwl_screen->egl_display,
+ xwl_pixmap->stream, eglGetError());
+ goto out;
+ }
+
DebugF("eglstream: win %d completes eglstream for pixmap %p, congrats!\n",
pending->window->drawable.id, pending->pixmap);
@@ -543,8 +628,16 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
xwl_pixmap->xwl_screen = xwl_screen;
xwl_pixmap->surface = EGL_NO_SURFACE;
xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
+ if (xwl_pixmap->stream == EGL_NO_STREAM_KHR) {
+ ErrorF("eglstream: Couldn't create EGL stream.\n");
+ goto fail;
+ }
stream_fd = eglGetStreamFileDescriptorKHR(xwl_screen->egl_display,
xwl_pixmap->stream);
+ if (stream_fd == EGL_NO_FILE_DESCRIPTOR_KHR) {
+ ErrorF("eglstream: Couldn't get EGL stream file descriptor.\n");
+ goto fail;
+ }
wl_array_init(&stream_attribs);
xwl_pixmap->buffer =
--
2.31.1

View File

@ -1,323 +0,0 @@
From 90188c2648edb137f3564bdea53012355473f105 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 16 Apr 2021 10:38:23 +0200
Subject: [PATCH xserver 13/27] xwayland/eglstream: Dissociate pending stream
from window
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Previously, we would have pending streams associated with top level X11
windows, keeping temporary accounting for the pending streams before
they get fully initialized for the xwl_pixmap which would be associated
with X11 pixmaps.
If the window content changes before the stream is ready, the
corresponding pending stream would be marked as invalid and the pending
stream would be eventually removed once the stream becomes ready.
Since commit affc47452 - "xwayland: Drop the separate refcount for the
xwl_pixmap", we no longer keep a separate reference counter for the
xwl_pixmap, but rather tie it to the X11 pixmap lifespan. Yet, the
pending stream would still be associated with the X11 toplevel window.
Dissociate the pending streams from the X11 toplevel window, to keep it
tied only to the xwl_pixmap so that we can have:
- pixmap <-> xwl_pixmap
- xwl_pixmap <-> pending stream
Of course, the pending streams remain temporary and get removed as soon
as the ready callback is triggered, but the pending streams are not
linked to the X11 window anymore which can change their content, and
therefore their X11 pixmap at any time.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit cb61ecc7291cfbed2f76d4437cd7450b8e4dab00)
---
hw/xwayland/xwayland-glamor-eglstream.c | 131 +++++++++++-------------
1 file changed, 60 insertions(+), 71 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 77b24a4b4..32f9a326f 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -93,6 +93,7 @@ struct xwl_pixmap {
/* add any new <= 4-byte member here to avoid holes on 64-bit */
struct xwl_screen *xwl_screen;
struct wl_buffer *buffer;
+ struct xwl_eglstream_pending_stream *pending_stream;
/* XWL_PIXMAP_EGLSTREAM. */
EGLStreamKHR stream;
@@ -103,7 +104,6 @@ struct xwl_pixmap {
};
static DevPrivateKeyRec xwl_eglstream_private_key;
-static DevPrivateKeyRec xwl_eglstream_window_private_key;
static inline struct xwl_eglstream_private *
xwl_eglstream_get(struct xwl_screen *xwl_screen)
@@ -112,21 +112,6 @@ xwl_eglstream_get(struct xwl_screen *xwl_screen)
&xwl_eglstream_private_key);
}
-static inline struct xwl_eglstream_pending_stream *
-xwl_eglstream_window_get_pending(WindowPtr window)
-{
- return dixLookupPrivate(&window->devPrivates,
- &xwl_eglstream_window_private_key);
-}
-
-static inline void
-xwl_eglstream_window_set_pending(WindowPtr window,
- struct xwl_eglstream_pending_stream *stream)
-{
- dixSetPrivate(&window->devPrivates,
- &xwl_eglstream_window_private_key, stream);
-}
-
static GLint
xwl_eglstream_compile_glsl_prog(GLenum type, const char *source)
{
@@ -323,7 +308,6 @@ xwl_glamor_eglstream_destroy_pending_stream(struct xwl_eglstream_pending_stream
{
if (pending->cb)
wl_callback_destroy(pending->cb);
- xwl_eglstream_window_set_pending(pending->window, NULL);
xorg_list_del(&pending->link);
free(pending);
}
@@ -331,16 +315,9 @@ xwl_glamor_eglstream_destroy_pending_stream(struct xwl_eglstream_pending_stream
static void
xwl_glamor_eglstream_remove_pending_stream(struct xwl_pixmap *xwl_pixmap)
{
- struct xwl_eglstream_private *xwl_eglstream =
- xwl_eglstream_get(xwl_pixmap->xwl_screen);
- struct xwl_eglstream_pending_stream *pending;
-
- xorg_list_for_each_entry(pending,
- &xwl_eglstream->pending_streams, link) {
- if (pending->xwl_pixmap == xwl_pixmap) {
- xwl_glamor_eglstream_destroy_pending_stream(pending);
- break;
- }
+ if (xwl_pixmap->pending_stream) {
+ xwl_glamor_eglstream_destroy_pending_stream(xwl_pixmap->pending_stream);
+ xwl_pixmap->pending_stream = NULL;
}
}
@@ -363,23 +340,41 @@ xwl_glamor_eglstream_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
return xwl_pixmap_get(pixmap)->buffer;
}
+static void
+xwl_eglstream_maybe_set_pending_stream_invalid(PixmapPtr pixmap)
+{
+ struct xwl_pixmap *xwl_pixmap;
+ struct xwl_eglstream_pending_stream *pending;
+
+ xwl_pixmap = xwl_pixmap_get(pixmap);
+ if (!xwl_pixmap)
+ return;
+
+ pending = xwl_pixmap->pending_stream;
+ if (!pending)
+ return;
+
+ pending->is_valid = FALSE;
+}
+
static void
xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
{
- struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
- struct xwl_eglstream_pending_stream *pending;
+ PixmapPtr old_pixmap;
- pending = xwl_eglstream_window_get_pending(window);
- if (pending) {
- /* The pixmap for this window has changed before the compositor
- * finished attaching the consumer for the window's pixmap's original
- * eglstream. A producer can no longer be attached, so the stream's
- * useless
- */
- pending->is_valid = FALSE;
- }
+ /* The pixmap for this window has changed.
+ * If that occurs while there is a stream pending, i.e. before the
+ * compositor has finished attaching the consumer for the window's
+ * pixmap's original eglstream, then a producer could no longer be
+ * attached, so the stream would be useless.
+ */
+ old_pixmap = (*screen->GetWindowPixmap) (window);
+ if (old_pixmap)
+ xwl_eglstream_maybe_set_pending_stream_invalid(old_pixmap);
xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
(*xwl_screen->screen->SetWindowPixmap)(window, pixmap);
@@ -489,16 +484,18 @@ xwl_eglstream_print_error(EGLDisplay egl_display,
* - Receive pixmap B's stream callback, fall over and fail because the
* window's surface now incorrectly has pixmap A's stream attached to it.
*
- * We work around this problem by keeping a queue of pending streams, and
- * only allowing one queue entry to exist for each window. In the scenario
- * listed above, this should happen:
+ * We work around this problem by keeping a pending stream associated with
+ * the xwl_pixmap, which itself is associated with the window pixmap.
+ * In the scenario listed above, this should happen:
*
* - Begin processing X events...
- * - A window is resized, causing us to add an eglstream (known as eglstream
- * A) waiting for its consumer to finish attachment to be added to the
- * queue.
+ * - A window is resized, a new window pixmap is created causing us to
+ * add an eglstream (known as eglstream A) waiting for its consumer
+ * to finish attachment.
* - Resize on same window happens. We invalidate the previously pending
- * stream and add another one to the pending queue (known as eglstream B).
+ * stream on the old window pixmap.
+ * A new window pixmap is attached to the window and another pending
+ * stream is created for that new pixmap (known as eglstream B).
* - Begin processing Wayland events...
* - Receive invalidated callback from compositor for eglstream A, destroy
* stream.
@@ -515,6 +512,7 @@ xwl_eglstream_consumer_ready_callback(void *data,
xwl_eglstream_get(xwl_screen);
struct xwl_pixmap *xwl_pixmap;
struct xwl_eglstream_pending_stream *pending;
+ PixmapPtr pixmap;
Bool found = FALSE;
xorg_list_for_each_entry(pending, &xwl_eglstream->pending_streams, link) {
@@ -528,6 +526,9 @@ xwl_eglstream_consumer_ready_callback(void *data,
wl_callback_destroy(callback);
pending->cb = NULL;
+ xwl_pixmap = pending->xwl_pixmap;
+ pixmap = pending->pixmap;
+
if (!pending->is_valid) {
xwl_eglstream_destroy_pixmap_stream(pending->xwl_pixmap);
goto out;
@@ -535,12 +536,11 @@ xwl_eglstream_consumer_ready_callback(void *data,
xwl_glamor_egl_make_current(xwl_screen);
- xwl_pixmap = pending->xwl_pixmap;
xwl_pixmap->surface = eglCreateStreamProducerSurfaceKHR(
xwl_screen->egl_display, xwl_eglstream->config,
xwl_pixmap->stream, (int[]) {
- EGL_WIDTH, pending->pixmap->drawable.width,
- EGL_HEIGHT, pending->pixmap->drawable.height,
+ EGL_WIDTH, pixmap->drawable.width,
+ EGL_HEIGHT, pixmap->drawable.height,
EGL_NONE
});
@@ -555,14 +555,14 @@ xwl_eglstream_consumer_ready_callback(void *data,
pending->window->drawable.id, pending->pixmap);
out:
- xwl_glamor_eglstream_destroy_pending_stream(pending);
+ xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
}
static const struct wl_callback_listener consumer_ready_listener = {
xwl_eglstream_consumer_ready_callback
};
-static void
+static struct xwl_eglstream_pending_stream *
xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
WindowPtr window, PixmapPtr pixmap)
{
@@ -570,14 +570,8 @@ xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
xwl_eglstream_get(xwl_screen);
struct xwl_eglstream_pending_stream *pending_stream;
-#ifdef DEBUG
- if (!xwl_eglstream_window_get_pending(window))
- DebugF("eglstream: win %d begins new eglstream for pixmap %p\n",
- window->drawable.id, pixmap);
- else
- DebugF("eglstream: win %d interrupts and replaces pending eglstream for pixmap %p\n",
- window->drawable.id, pixmap);
-#endif
+ DebugF("eglstream: win %d queues new pending stream for pixmap %p\n",
+ window->drawable.id, pixmap);
pending_stream = malloc(sizeof(*pending_stream));
pending_stream->window = window;
@@ -586,11 +580,12 @@ xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
pending_stream->is_valid = TRUE;
xorg_list_init(&pending_stream->link);
xorg_list_add(&pending_stream->link, &xwl_eglstream->pending_streams);
- xwl_eglstream_window_set_pending(window, pending_stream);
pending_stream->cb = wl_display_sync(xwl_screen->display);
wl_callback_add_listener(pending_stream->cb, &consumer_ready_listener,
xwl_screen);
+
+ return pending_stream;
}
static void
@@ -663,7 +658,8 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
wl_eglstream_controller_attach_eglstream_consumer(
xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
- xwl_eglstream_queue_pending_stream(xwl_screen, window, pixmap);
+ xwl_pixmap->pending_stream =
+ xwl_eglstream_queue_pending_stream(xwl_screen, window, pixmap);
fail:
if (stream_fd >= 0)
@@ -674,22 +670,19 @@ static Bool
xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- struct xwl_eglstream_pending_stream *pending =
- xwl_eglstream_window_get_pending(xwl_window->window);
PixmapPtr pixmap =
(*xwl_screen->screen->GetWindowPixmap)(xwl_window->window);
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap) {
+ struct xwl_eglstream_pending_stream *pending = xwl_pixmap->pending_stream;
+
if (pending) {
/* Wait for the compositor to finish connecting the consumer for
* this eglstream */
- if (pending->is_valid)
- return FALSE;
+ assert(pending->is_valid);
- /* The pixmap for this window was changed before the compositor
- * finished connecting the eglstream for the window's previous
- * pixmap. Begin creating a new eglstream. */
+ return FALSE;
} else {
return TRUE;
}
@@ -1190,10 +1183,6 @@ xwl_glamor_eglstream_init_screen(struct xwl_screen *xwl_screen)
xwl_eglstream->SetWindowPixmap = screen->SetWindowPixmap;
screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
- if (!dixRegisterPrivateKey(&xwl_eglstream_window_private_key,
- PRIVATE_WINDOW, 0))
- return FALSE;
-
return TRUE;
}
--
2.31.1

View File

@ -1,73 +0,0 @@
From f76dd86f5bbdccb3655ac58365e4604d03de65f5 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 14 Apr 2021 17:31:08 +0200
Subject: [PATCH xserver 14/27] xwayland/eglstream: Keep a reference to the
pixmap
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Commit affc47452 - "xwayland: Drop the separate refcount for the
xwl_pixmap" removed the separate reference counter for the xwl_pixmap
which holds the EGLStream.
While that works fine for the common case, if the window's pixmap is
changed before the stream is ready, the older pixmap will be destroyed
and the xwl_pixmap along with it, even if the compositor is still using
the stream.
The code that was removed with commit affc47452 was taking care of that
by increasing the separate reference counter for the xwl_pixmap, but it
no longer the case.
As a result, we may end up with the EGL stream in the wrong state when
trying to use it, which will cascade down into all sort of issues.
To avoid the problem, increase the reference count on the pixmap when it
is marked as invalid in EGLStream's SetWindowPixmap().
This way, the xwl_pixmap and the EGLStream are kept until released by
the compositor, even when the pixmap changes before stream is ready.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
Fixes: affc47452 xwayland: Drop the separate refcount for the xwl_pixmap
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit e19bf86c17ef9c802fea24410cc6b1f51a19ce7f)
---
hw/xwayland/xwayland-glamor-eglstream.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 32f9a326f..807bfcb1d 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -355,6 +355,13 @@ xwl_eglstream_maybe_set_pending_stream_invalid(PixmapPtr pixmap)
return;
pending->is_valid = FALSE;
+
+ /* The compositor may still be using the stream, so we can't destroy
+ * it yet. We'll only have a guarantee that the stream is safe to
+ * destroy once we receive the pending wl_display_sync() for this
+ * stream
+ */
+ pending->pixmap->refcnt++;
}
static void
@@ -530,8 +537,9 @@ xwl_eglstream_consumer_ready_callback(void *data,
pixmap = pending->pixmap;
if (!pending->is_valid) {
- xwl_eglstream_destroy_pixmap_stream(pending->xwl_pixmap);
- goto out;
+ xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
+ dixDestroyPixmap(pixmap, 0);
+ return;
}
xwl_glamor_egl_make_current(xwl_screen);
--
2.31.1

View File

@ -1,146 +0,0 @@
From a68e939342aed0ea11c737d166e506442e048e90 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Tue, 27 Apr 2021 14:17:19 +0200
Subject: [PATCH xserver 15/27] xwayland/eglstream: Drop the list of pending
streams
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Now that the pending stream is associated with the xwl_pixmap for
EGLStream and the xwl_pixmap itself is associated to the pixmap, we have
a reliable way to get to those data from any pending stream.
As a result, the list of pending streams that we keep in the EGLStream
global structure becomes useless.
So we can drop the pending stream's xwl_pixmap and also the list of
pending streams altogether, and save us a walk though that list for each
callback.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Suggested-by: Michel Dänzer <mdaenzer@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit bee2ebb29f0999862ab39af26c673c00af40b082)
---
hw/xwayland/xwayland-glamor-eglstream.c | 41 ++++++-------------------
1 file changed, 9 insertions(+), 32 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 807bfcb1d..399a691d3 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -55,12 +55,9 @@ struct xwl_eglstream_pending_stream {
PixmapPtr pixmap;
WindowPtr window;
- struct xwl_pixmap *xwl_pixmap;
struct wl_callback *cb;
Bool is_valid;
-
- struct xorg_list link;
};
struct xwl_eglstream_private {
@@ -73,8 +70,6 @@ struct xwl_eglstream_private {
SetWindowPixmapProcPtr SetWindowPixmap;
- struct xorg_list pending_streams;
-
Bool have_egl_damage;
GLint blit_prog;
@@ -308,7 +303,6 @@ xwl_glamor_eglstream_destroy_pending_stream(struct xwl_eglstream_pending_stream
{
if (pending->cb)
wl_callback_destroy(pending->cb);
- xorg_list_del(&pending->link);
free(pending);
}
@@ -514,28 +508,16 @@ xwl_eglstream_consumer_ready_callback(void *data,
struct wl_callback *callback,
uint32_t time)
{
- struct xwl_screen *xwl_screen = data;
+ struct xwl_eglstream_pending_stream *pending = data;
+ PixmapPtr pixmap = pending->pixmap;
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+ struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
- struct xwl_pixmap *xwl_pixmap;
- struct xwl_eglstream_pending_stream *pending;
- PixmapPtr pixmap;
- Bool found = FALSE;
-
- xorg_list_for_each_entry(pending, &xwl_eglstream->pending_streams, link) {
- if (pending->cb == callback) {
- found = TRUE;
- break;
- }
- }
- assert(found);
wl_callback_destroy(callback);
pending->cb = NULL;
- xwl_pixmap = pending->xwl_pixmap;
- pixmap = pending->pixmap;
-
if (!pending->is_valid) {
xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
dixDestroyPixmap(pixmap, 0);
@@ -571,11 +553,10 @@ static const struct wl_callback_listener consumer_ready_listener = {
};
static struct xwl_eglstream_pending_stream *
-xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
- WindowPtr window, PixmapPtr pixmap)
+xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
{
- struct xwl_eglstream_private *xwl_eglstream =
- xwl_eglstream_get(xwl_screen);
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+ struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
struct xwl_eglstream_pending_stream *pending_stream;
DebugF("eglstream: win %d queues new pending stream for pixmap %p\n",
@@ -584,14 +565,11 @@ xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
pending_stream = malloc(sizeof(*pending_stream));
pending_stream->window = window;
pending_stream->pixmap = pixmap;
- pending_stream->xwl_pixmap = xwl_pixmap_get(pixmap);
pending_stream->is_valid = TRUE;
- xorg_list_init(&pending_stream->link);
- xorg_list_add(&pending_stream->link, &xwl_eglstream->pending_streams);
pending_stream->cb = wl_display_sync(xwl_screen->display);
wl_callback_add_listener(pending_stream->cb, &consumer_ready_listener,
- xwl_screen);
+ pending_stream);
return pending_stream;
}
@@ -667,7 +645,7 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
xwl_pixmap->pending_stream =
- xwl_eglstream_queue_pending_stream(xwl_screen, window, pixmap);
+ xwl_eglstream_queue_pending_stream(window, pixmap);
fail:
if (stream_fd >= 0)
@@ -1249,7 +1227,6 @@ xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
&xwl_eglstream_private_key, xwl_eglstream);
xwl_eglstream->egl_device = egl_device;
- xorg_list_init(&xwl_eglstream->pending_streams);
xwl_screen->eglstream_backend.init_egl = xwl_glamor_eglstream_init_egl;
xwl_screen->eglstream_backend.init_wl_registry = xwl_glamor_eglstream_init_wl_registry;
--
2.31.1

View File

@ -1,49 +0,0 @@
From 9601f2cc5c94b9db4c7f8da404dae53b9609c995 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 19 Apr 2021 18:11:19 +0200
Subject: [PATCH xserver 16/27] xwayland/eglstream: Do not commit without
surface
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The EGL surface for the xwl_pixmap is created once the stream is ready
and valid.
If the pixmap's EGL surface fails, for whatever reason, the xwl_pixmap
will be unusable and will end up as an invalid wl_buffer.
Make sure we do not allow commits in that case and recreate the
xwl_pixmap/stream.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1156
(cherry picked from commit 098e0f52c088c6eb52c7e54c5a11cefabd480908)
---
hw/xwayland/xwayland-glamor-eglstream.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 399a691d3..ce066cd9e 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -670,7 +670,14 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
return FALSE;
} else {
- return TRUE;
+ if (xwl_pixmap->surface != EGL_NO_SURFACE)
+ return TRUE;
+
+ /* The pending stream got removed, we have a xwl_pixmap and
+ * yet we do not have a surface.
+ * So something went wrong with the surface creation, retry.
+ */
+ xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
}
}
--
2.31.1

View File

@ -1,47 +0,0 @@
From 39df6934d5a9a132c2e87456e35094b7e81a238e Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 19 Apr 2021 14:52:38 +0200
Subject: [PATCH xserver 17/27] xwayland/eglstream: Fix calloc/malloc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use calloc() instead of malloc() like the rest of the code.
Also fix the arguments of calloc() calls to match the definition which
is calloc(size_t nmemb, size_t size).
This is a cleanup patch, no functional change.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit a45799971083c47082d085d3732a5b12692cf75b)
---
hw/xwayland/xwayland-glamor-eglstream.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index ce066cd9e..3a3caa976 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -562,7 +562,7 @@ xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
DebugF("eglstream: win %d queues new pending stream for pixmap %p\n",
window->drawable.id, pixmap);
- pending_stream = malloc(sizeof(*pending_stream));
+ pending_stream = calloc(1, sizeof(*pending_stream));
pending_stream->window = window;
pending_stream->pixmap = pixmap;
pending_stream->is_valid = TRUE;
@@ -596,7 +596,7 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
struct wl_array stream_attribs;
int stream_fd = -1;
- xwl_pixmap = calloc(sizeof(*xwl_pixmap), 1);
+ xwl_pixmap = calloc(1, sizeof(*xwl_pixmap));
if (!xwl_pixmap)
FatalError("Not enough memory to create pixmap\n");
xwl_pixmap_set_private(pixmap, xwl_pixmap);
--
2.31.1

View File

@ -1,56 +0,0 @@
From a964ccdadf351d90482df00c272dee3634f7a8ee Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 30 Apr 2021 09:02:29 +0200
Subject: [PATCH xserver 18/27] xwayland/eglstream: Check eglSwapBuffers()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
EGLstream's post_damage() would unconditionally return success
regardless of the actual status of the eglSwapBuffers().
Yet, if eglSwapBuffers() fails, we should not post the corresponding
damage as they wouldn't match the actual content of the buffer.
Use the eglSwapBuffers() return value as the return value for
post_damage() and do not take a refrence on the pixmap if it fails.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit b583395cd38ad101c7541bd8b0e91143ced44703)
---
hw/xwayland/xwayland-glamor-eglstream.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 3a3caa976..6721acfe8 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -750,14 +750,20 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
if (xwl_eglstream->have_egl_damage)
- eglSwapBuffersWithDamageKHR(xwl_screen->egl_display,
- xwl_pixmap->surface, egl_damage, 1);
+ status = eglSwapBuffersWithDamageKHR(xwl_screen->egl_display,
+ xwl_pixmap->surface,
+ egl_damage, 1);
else
- eglSwapBuffers(xwl_screen->egl_display, xwl_pixmap->surface);
+ status = eglSwapBuffers(xwl_screen->egl_display,
+ xwl_pixmap->surface);
+
+ if (!status) {
+ ErrorF("eglstream: buffer swap failed, not posting damage\n");
+ goto out;
+ }
/* hang onto the pixmap until the compositor has released it */
pixmap->refcnt++;
- status = TRUE;
out:
/* Restore previous state */
--
2.31.1

View File

@ -1,89 +0,0 @@
From 7b06e468b37164eeaa18fc32cba801de0eee4eb1 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Tue, 4 May 2021 10:56:38 +0200
Subject: [PATCH xserver 19/27] xwayland/eglstream: Do not always increment
pixmap refcnt on commit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Currently, the EGLstream backend would increment the pixmap refcount for
each commit, and decrease that refcount on the wl_buffer release
callback.
But that's relying on the compositor sending us a release callback for
each commit, otherwise the pixmap refcount will keep increasing and the
pixmap will be leaked.
So instead, increment the refcount on the pixmap only when we have not
received a release notification for the wl_buffer, to avoid increasing
the pixmap refcount more than once without a corresponding release
event.
This way, if the pixmap is still in use when released on the X11 side,
the EGL stream will be kept until the compositor releases it.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Suggested-by: Michel Dänzer <mdaenzer@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit d85bfa6ab7495281516f3a4b05dc1ff0b2c4bf91)
---
hw/xwayland/xwayland-glamor-eglstream.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 6721acfe8..64f4e31f5 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -89,6 +89,7 @@ struct xwl_pixmap {
struct xwl_screen *xwl_screen;
struct wl_buffer *buffer;
struct xwl_eglstream_pending_stream *pending_stream;
+ Bool wait_for_buffer_release;
/* XWL_PIXMAP_EGLSTREAM. */
EGLStreamKHR stream;
@@ -577,8 +578,16 @@ xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
static void
xwl_eglstream_buffer_release_callback(void *data)
{
- /* drop the reference we took in post_damage, freeing if necessary */
- dixDestroyPixmap(data, 0);
+ PixmapPtr pixmap = data;
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+ assert(xwl_pixmap);
+
+ if (xwl_pixmap->wait_for_buffer_release) {
+ xwl_pixmap->wait_for_buffer_release = FALSE;
+ /* drop the reference we took in the ready callback, freeing if necessary */
+ dixDestroyPixmap(pixmap, 0);
+ }
}
static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
@@ -606,6 +615,7 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
xwl_glamor_egl_make_current(xwl_screen);
+ xwl_pixmap->wait_for_buffer_release = FALSE;
xwl_pixmap->xwl_screen = xwl_screen;
xwl_pixmap->surface = EGL_NO_SURFACE;
xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
@@ -762,8 +772,11 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
goto out;
}
- /* hang onto the pixmap until the compositor has released it */
- pixmap->refcnt++;
+ if (!xwl_pixmap->wait_for_buffer_release) {
+ /* hang onto the pixmap until the compositor has released it */
+ pixmap->refcnt++;
+ xwl_pixmap->wait_for_buffer_release = TRUE;
+ }
out:
/* Restore previous state */
--
2.31.1

View File

@ -1,51 +0,0 @@
From 9519ebe96344ec64e8f18eae2420df101c446a1a Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 30 Apr 2021 16:23:10 +0200
Subject: [PATCH xserver 20/27] xwayland/eglstream: Set ALU to GXCopy for
blitting
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The EGLstream backend's post damage function uses a shader and
glDrawArrays() to copy the data from the glamor's pixmap texture prior
to do the eglSwapBuffers().
However, glDrawArrays() can be affected by the GL state, and therefore
not reliably produce the expected copy, causing the content of the
buffer to be corrupted.
Make sure to set the ALU to GXCopy prior to call glDrawArrays() to get
the expected result.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Suggested-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 012350e3db47fef0404346f55968032e62004fcf)
---
hw/xwayland/xwayland-glamor-eglstream.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 64f4e31f5..2094d293a 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -33,6 +33,7 @@
#define EGL_NO_X11
#include <glamor_egl.h>
#include <glamor.h>
+#include <glamor_priv.h>
#include <glamor_transform.h>
#include <glamor_transfer.h>
@@ -727,6 +728,8 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
* won't actually draw to it
*/
xwl_glamor_egl_make_current(xwl_screen);
+ glamor_set_alu(xwl_screen->screen, GXcopy);
+
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (eglGetCurrentSurface(EGL_READ) != xwl_pixmap->surface ||
--
2.31.1

View File

@ -1,43 +0,0 @@
From 64deb9471c7d9cad4c2ec1de1fba6a35c9af8e68 Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Fri, 14 May 2021 08:26:49 -0400
Subject: [PATCH xserver 21/27] xwayland/eglstream: allow commits to dma-buf
backed pixmaps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
As of commit 098e0f52 xwl_glamor_eglstream_allow_commits will not allow commits
if the xwl_pixmap does not have an EGLSurface. This is valid for pixmaps backed
by an EGLStream, however pixmaps backed by a dma-buf for OpenGL or Vulkan
rendering will never have an EGLSurface. Unlike EGLStream backed pixmaps,
though, glamor will render directly to the buffer that Xwayland passes to the
compositor. Hence, they don't require the intermediate copy in
xwl_glamor_eglstream_post_damage that EGLStream backed pixmaps do, so there is
no need for an EGLSurface.
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 3d33d885fcd1215a74c1819278cf6f9557c9860b)
---
hw/xwayland/xwayland-glamor-eglstream.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 2094d293a..2d0827709 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -681,7 +681,8 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
return FALSE;
} else {
- if (xwl_pixmap->surface != EGL_NO_SURFACE)
+ if (xwl_pixmap->surface != EGL_NO_SURFACE ||
+ xwl_pixmap->type == XWL_PIXMAP_DMA_BUF)
return TRUE;
/* The pending stream got removed, we have a xwl_pixmap and
--
2.31.1

View File

@ -1,76 +0,0 @@
From 29cba30948cda34e744314343109964ff9ed515c Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Tue, 11 May 2021 17:00:21 -0400
Subject: [PATCH xserver 22/27] xwayland/eglstream: flush stream after
eglSwapBuffers
When eglSwapBuffers inserts a new frame into a window's stream, there may be a
delay before the state of the consumer end of the stream is updated to reflect
this. If the subsequent wl_surface_attach, wl_surface_damage, wl_surface_commit
calls are received by the compositor before then, it will (typically) re-use
the previous frame acquired from the stream instead of the latest one.
This can leave the window displaying out-of-date contents, which might never be
updated thereafter.
To fix this, after calling eglSwapBuffers, xwl_glamor_eglstream_post_damage
should call eglStreamFlushNV. This call will block until it can be guaranteed
that the state of the consumer end of the stream has been updated to reflect
that a new frame is available.
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1171
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
(cherry picked from commit 7515c23a416825f0db51f9b445279b12d5918ebf)
---
hw/xwayland/xwayland-glamor-eglstream.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 2d0827709..c583a1390 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -72,6 +72,7 @@ struct xwl_eglstream_private {
SetWindowPixmapProcPtr SetWindowPixmap;
Bool have_egl_damage;
+ Bool have_egl_stream_flush;
GLint blit_prog;
GLuint blit_vao;
@@ -776,6 +777,13 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
goto out;
}
+#ifdef EGL_NV_stream_flush
+ if (xwl_eglstream->have_egl_stream_flush)
+ /* block until stream state is updated on the compositor's side */
+ eglStreamFlushNV(xwl_screen->egl_display,
+ xwl_pixmap->stream);
+#endif
+
if (!xwl_pixmap->wait_for_buffer_release) {
/* hang onto the pixmap until the compositor has released it */
pixmap->refcnt++;
@@ -1173,6 +1181,18 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
ErrorF("Driver lacks EGL_KHR_swap_buffers_with_damage, performance "
"will be affected\n");
+#ifdef EGL_NV_stream_flush
+ xwl_eglstream->have_egl_stream_flush =
+ epoxy_has_egl_extension(xwl_screen->egl_display,
+ "EGL_NV_stream_flush");
+#else
+ xwl_eglstream->have_egl_stream_flush = FALSE;
+#endif /* EGL_NV_stream_flush */
+
+ if (!xwl_eglstream->have_egl_stream_flush)
+ ErrorF("EGL_NV_stream_flush not available, "
+ "this may cause visible corruption.\n");
+
xwl_eglstream_init_shaders(xwl_screen);
if (epoxy_has_gl_extension("GL_OES_EGL_image") &&
--
2.31.1

View File

@ -1,57 +0,0 @@
From 4c01758cbe7db02d84ac0cba0c626e855bf927d6 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Thu, 20 May 2021 12:11:42 +0200
Subject: [PATCH xserver 23/27] xwayland: Add preferred GLVND vendor to
xwl_screen
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If Xwayland's EGLstream backend supports hardware acceleration with the
NVIDIA closed-source driver, the GLX library also needs to be one
shipped by NVIDIA, that's what GLVND is for.
Add a new member to the xwl_screen that the backend can optionally set
to the preferred GLVND vendor to use.
If not set, "mesa" is assumed.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 24fc8aea1e4bbaba780f1a316fba797a0198f603)
---
hw/xwayland/xwayland-glx.c | 3 +++
hw/xwayland/xwayland-screen.h | 3 +++
2 files changed, 6 insertions(+)
diff --git a/hw/xwayland/xwayland-glx.c b/hw/xwayland/xwayland-glx.c
index 7e2a87fc1..eba8946ab 100644
--- a/hw/xwayland/xwayland-glx.c
+++ b/hw/xwayland/xwayland-glx.c
@@ -378,6 +378,9 @@ egl_screen_probe(ScreenPtr pScreen)
return NULL;
}
+ if (!screen->base.glvnd && xwl_screen->glvnd_vendor)
+ screen->base.glvnd = strdup(xwl_screen->glvnd_vendor);
+
if (!screen->base.glvnd)
screen->base.glvnd = strdup("mesa");
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 5fe4712bd..b965dddd7 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -107,6 +107,9 @@ struct xwl_screen {
struct glamor_context *glamor_ctx;
Atom allow_commits_prop;
+
+ /* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
+ const char *glvnd_vendor;
};
/* Apps which use randr/vidmode to change the mode when going fullscreen,
--
2.31.1

View File

@ -1,42 +0,0 @@
From 430eb872784c04e825126e0d7454f3a5bbefff70 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 17 May 2021 18:20:57 +0200
Subject: [PATCH xserver 24/27] xwayland/eglstream: Use "nvidia" for GLVND
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If the EGLStream backend is able to use hardware acceleration with the
NVIDIA closed source driver, we should use the "nvidia" GLX
implementation instead of the one from Mesa to take advantage of the
NVIDIA hardware accelerated rendering.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit fae58e9b03696a3890f9c876306c68ffa6f9ff30)
---
hw/xwayland/xwayland-glamor-eglstream.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index c583a1390..5e89849ff 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -1195,9 +1195,11 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
xwl_eglstream_init_shaders(xwl_screen);
- if (epoxy_has_gl_extension("GL_OES_EGL_image") &&
- !dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
- ErrorF("DRI3 initialization failed. Performance will be affected.\n");
+ if (epoxy_has_gl_extension("GL_OES_EGL_image")) {
+ if (dri3_screen_init(xwl_screen->screen, &xwl_dri3_info))
+ xwl_screen->glvnd_vendor = "nvidia";
+ else
+ ErrorF("DRI3 initialization failed. Performance will be affected.\n");
}
return TRUE;
--
2.31.1

View File

@ -1,35 +0,0 @@
From 0cb42b7de629e74afed9b19d47672cebfe08f12e Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Thu, 20 May 2021 16:46:33 +0200
Subject: [PATCH xserver 25/27] xwayland/eglstream: Log when GL_OES_EGL_image
is missing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
That will dramatically affect performance, might as well log when we
cannot use GL_OES_EGL_image with the NVIDIA closed-source driver.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit 34a58d7714025bc1043bf5282358406eb10e4b8e)
---
hw/xwayland/xwayland-glamor-eglstream.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
index 5e89849ff..0affc954c 100644
--- a/hw/xwayland/xwayland-glamor-eglstream.c
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
@@ -1200,6 +1200,8 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
xwl_screen->glvnd_vendor = "nvidia";
else
ErrorF("DRI3 initialization failed. Performance will be affected.\n");
+ } else {
+ ErrorF("Driver lacks GL_OES_EGL_image, performance will be affected.\n");
}
return TRUE;
--
2.31.1

View File

@ -1,60 +0,0 @@
From a604a0a26791e9f352aad27232127d729bca4334 Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Thu, 10 Dec 2020 14:24:32 -0800
Subject: [PATCH xserver 26/27] glx: don't create implicit GLXWindow if one
already exists
If a GLXMakeCurrent request specifies an X window as its drawable,
__glXGetDrawable will implicitly create a GLXWindow for it. However,
the client may have already explicitly created a GLXWindow for that X
window. If that happens, two __glXDrawableRes resources will be added
to the window.
If the explicitly-created GLXWindow is later destroyed by the client,
DrawableGone will call FreeResourceByType on the X window, but this
will actually free the resource for the implicitly-created GLXWindow,
since that one would be at the head of the list.
Then if the X window is destroyed after that, the resource for the
explicitly-created GLXWindow will be freed. But that GLXWindow was
already destroyed above. This crashes the server when it tries to call
the destroyed GLXWindow's destructor. It also means the
implicitly-created GLXWindow would have been leaked since the
FreeResourceByType call mentioned above skips calling the destructor.
To fix this, if __glXGetDrawable is given an X window, it should check
if there is already a GLXWindow associated with it, and only create an
implicit one if there is not.
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
(cherry picked from commit b7a85e44da91d1663d5b4eabac06327c92a80f91)
---
glx/glxcmds.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 37576b6ef..1b9ad6d14 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -487,8 +487,15 @@ __glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client,
__GLXscreen *pGlxScreen;
int rc;
- if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
- DixWriteAccess, &pGlxDraw, &rc)) {
+ rc = dixLookupResourceByType((void **)&pGlxDraw, drawId,
+ __glXDrawableRes, client, DixWriteAccess);
+ if (rc == Success &&
+ /* If pGlxDraw->drawId == drawId, drawId is a valid GLX drawable.
+ * Otherwise, if pGlxDraw->type == GLX_DRAWABLE_WINDOW, drawId is
+ * an X window, but the client has already created a GLXWindow
+ * associated with it, so we don't want to create another one. */
+ (pGlxDraw->drawId == drawId ||
+ pGlxDraw->type == GLX_DRAWABLE_WINDOW)) {
if (glxc != NULL &&
glxc->config != NULL &&
glxc->config != pGlxDraw->config) {
--
2.31.1

View File

@ -1,45 +0,0 @@
From 1607ac6870f7cf67c30b96529ea5ca389c771a3d Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Thu, 3 Jun 2021 17:51:01 +0200
Subject: [PATCH xserver 27/27] glx: Set ContextTag for all contexts
Currently, xorgGlxMakeCurrent() would set the context tag only for
indirect GLX contexts.
However, several other places expect to find a context for the tag or
they would raise a GLXBadContextTag error, such as WaitGL() or WaitX().
Set the context tag for direct contexts as well, to avoid raising an
error and possibly killing the client and set currentClient.
Thanks to Erik Kurzinger <ekurzinger@nvidia.com> for spotting the issue.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
(cherry picked from commit c468d34c7208c9041f9c077b54a00ae9cccad6a3)
(cherry picked from commit aad61e8e03311eb8bae4f7db59e65634733eadc2)
---
glx/glxcmds.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 1b9ad6d14..8b2170306 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -662,10 +662,11 @@ xorgGlxMakeCurrent(ClientPtr client, GLXContextTag tag, XID drawId, XID readId,
glxc->readPriv = NULL;
return __glXError(GLXBadContext);
}
+ }
+ glxServer.setContextTagPrivate(client, newContextTag, glxc);
+ if (glxc)
glxc->currentClient = client;
- glxServer.setContextTagPrivate(client, newContextTag, glxc);
- }
if (prevglxc) {
prevglxc->currentClient = NULL;
--
2.31.1

View File

@ -8,8 +8,8 @@
Summary: Xwayland
Name: xorg-x11-server-Xwayland
Version: 21.1.1
Release: 6%{?gitdate:.%{gitdate}git%{shortcommit}}%{?dist}
Version: 21.1.3
Release: 15%{?gitdate:.%{gitdate}git%{shortcommit}}%{?dist}
URL: http://www.x.org
%if 0%{?gitdate}
@ -18,41 +18,75 @@ Source0: https://gitlab.freedesktop.org/xorg/%{pkgname}/-/archive/%{commit}/%{
Source0: https://www.x.org/pub/individual/xserver/%{pkgname}-%{version}.tar.xz
%endif
Patch1: 0001-xwayland-Move-dmabuf-interface-to-common-glamor-code.patch
Patch2: 0002-xwayland-move-formats-and-modifiers-functions-to-com.patch
Patch3: 0003-xwayland-Add-check_flip-glamor-backend-function.patch
Patch4: 0004-xwayland-implement-pixmap_from_buffers-for-the-eglst.patch
Patch5: 0005-xwayland-eglstream-fix-X11-rendering-to-flipping-GL-.patch
Patch6: 0006-xwayland-eglstream-Check-buffer-creation.patch
Patch7: 0007-xwayland-Check-buffer-prior-to-attaching-it.patch
Patch8: 0008-glamor-Dump-backtrace-on-GL-error.patch
Patch9: 0009-xwayland-glamor-Add-return-status-to-post_damage.patch
Patch10: 0010-xwayland-eglstream-Check-framebuffer-status.patch
Patch11: 0011-xwayland-eglstream-Small-refactoring.patch
Patch12: 0012-xwayland-eglstream-Add-more-error-checking.patch
Patch13: 0013-xwayland-eglstream-Dissociate-pending-stream-from-wi.patch
Patch14: 0014-xwayland-eglstream-Keep-a-reference-to-the-pixmap.patch
Patch15: 0015-xwayland-eglstream-Drop-the-list-of-pending-streams.patch
Patch16: 0016-xwayland-eglstream-Do-not-commit-without-surface.patch
Patch17: 0017-xwayland-eglstream-Fix-calloc-malloc.patch
Patch18: 0018-xwayland-eglstream-Check-eglSwapBuffers.patch
Patch19: 0019-xwayland-eglstream-Do-not-always-increment-pixmap-re.patch
Patch20: 0020-xwayland-eglstream-Set-ALU-to-GXCopy-for-blitting.patch
Patch21: 0021-xwayland-eglstream-allow-commits-to-dma-buf-backed-p.patch
Patch22: 0022-xwayland-eglstream-flush-stream-after-eglSwapBuffers.patch
Patch23: 0023-xwayland-Add-preferred-GLVND-vendor-to-xwl_screen.patch
Patch24: 0024-xwayland-eglstream-Use-nvidia-for-GLVND.patch
Patch25: 0025-xwayland-eglstream-Log-when-GL_OES_EGL_image-is-miss.patch
Patch26: 0026-glx-don-t-create-implicit-GLXWindow-if-one-already-e.patch
Patch27: 0027-glx-Set-ContextTag-for-all-contexts.patch
# https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/704
Patch28: 0001-xwayland-eglstream-Keep-pending-stream-if-the-pixmap.patch
Patch29: 0002-xwayland-eglstream-Remove-stream-validity.patch
Patch1: 0001-xwayland-eglstream-Demote-EGLstream-device-warning.patch
Patch2: 0002-xwayland-glamor-Change-errors-to-verbose-messages.patch
Patch3: 0003-xwayland-glamor-Log-backend-selected-for-debug.patch
Patch4: 0004-xwayland-eglstream-Prefer-EGLstream-if-available.patch
Patch5: 0001-present-Send-a-PresentConfigureNotify-event-for-dest.patch
# CVE-2021-4011
Patch10001: 0001-record-Fix-out-of-bounds-access-in-SwapCreateRegiste.patch
# CVE-2021-4009
Patch10002: 0002-xfixes-Fix-out-of-bounds-access-in-ProcXFixesCreateP.patch
# CVE-2021-4010
Patch10003: 0003-Xext-Fix-out-of-bounds-access-in-SProcScreenSaverSus.patch
# CVE-2021-4008
Patch10004: 0004-render-Fix-out-of-bounds-access-in-SProcRenderCompos.patch
# CVE-2022-2319/ZDI-CAN-16062, CVE-2022-2320/ZDI-CAN-16070
Patch10005: 0001-xkb-switch-to-array-index-loops-to-moving-pointers.patch
Patch10006: 0002-xkb-swap-XkbSetDeviceInfo-and-XkbSetDeviceInfoCheck.patch
Patch10007: 0003-xkb-add-request-length-validation-for-XkbSetGeometry.patch
# CVE-2022-3550
Patch10008: 0001-xkb-proof-GetCountedString-against-request-length-at.patch
# CVE-2022-3551
Patch10009: 0001-xkb-fix-some-possible-memleaks-in-XkbGetKbdByName.patch
# CVE-2022-46340
Patch10018: 0001-Xtest-disallow-GenericEvents-in-XTestSwapFakeInput.patch
# related to CVE-2022-46344
Patch10019: 0002-Xi-return-an-error-from-XI-property-changes-if-verif.patch
# CVE-2022-46344
Patch10020: 0003-Xi-avoid-integer-truncation-in-length-check-of-ProcX.patch
# CVE-2022-46341
Patch10021: 0004-Xi-disallow-passive-grabs-with-a-detail-255.patch
# CVE-2022-46343
Patch10022: 0005-Xext-free-the-screen-saver-resource-when-replacing-i.patch
# CVE-2022-46342
Patch10023: 0006-Xext-free-the-XvRTVideoNotify-when-turning-off-from-.patch
# CVE-2022-4283
Patch10024: 0007-xkb-reset-the-radio_groups-pointer-to-NULL-after-fre.patch
# Follow-up to CVE-2022-46340
Patch10025: 0008-Xext-fix-invalid-event-type-mask-in-XTestSwapFakeInp.patch
# CVE-2023-0494
Patch10026: 0001-Xi-fix-potential-use-after-free-in-DeepCopyPointerCl.patch
# CVE-2023-1393
Patch10027: 0001-composite-Fix-use-after-free-of-the-COW.patch
# CVE-2023-5367
Patch10028: 0001-Xi-randr-fix-handling-of-PropModeAppend-Prepend.patch
# CVE-2023-6478
Patch10029: 0001-randr-avoid-integer-truncation-in-length-check-of-Pr.patch
# CVE-2023-6377
Patch10030: 0001-Xi-allocate-enough-XkbActions-for-our-buttons.patch
# Fix for CVE-2023-6816, ZDI-CAN-22664, ZDI-CAN-22665
Patch10031: 0001-dix-allocate-enough-space-for-logical-button-maps.patch
# Fix for CVE-2024-0229, ZDI-CAN-22678
Patch10032: 0002-dix-Allocate-sufficient-xEvents-for-our-DeviceStateN.patch
Patch10033: 0003-dix-fix-DeviceStateNotify-event-calculation.patch
Patch10034: 0004-Xi-when-creating-a-new-ButtonClass-set-the-number-of.patch
# Fix for CVE-2024-21885, ZDI-CAN-22744
Patch10035: 0005-Xi-flush-hierarchy-events-after-adding-removing-mast.patch
# Fix for CVE-2024-21886, ZDI-CAN-22840
Patch10036: 0006-Xi-do-not-keep-linked-list-pointer-during-recursion.patch
Patch10037: 0007-dix-when-disabling-a-master-float-disabled-slaved-de.patch
# Fix for CVE-2024-0408
Patch10038: 0008-glx-Call-XACE-hooks-on-the-GLX-buffer.patch
# Fix for CVE-2024-0409
Patch10039: 0009-ephyr-xwayland-Use-the-proper-private-key-for-cursor.patch
License: MIT
Requires: xorg-x11-server-common
Requires: libEGL
Requires: libepoxy >= 1.5.5
BuildRequires: gcc
BuildRequires: git-core
@ -64,7 +98,7 @@ BuildRequires: pkgconfig(wayland-protocols)
BuildRequires: pkgconfig(wayland-eglstream-protocols)
BuildRequires: pkgconfig(dmx)
BuildRequires: pkgconfig(epoxy)
BuildRequires: pkgconfig(epoxy) >= 1.5.5
BuildRequires: pkgconfig(fontenc)
BuildRequires: pkgconfig(libdrm) >= 2.4.0
BuildRequires: pkgconfig(libssl)
@ -154,28 +188,75 @@ rm -Rf $RPM_BUILD_ROOT%{_localstatedir}/lib/xkb
%{_libdir}/pkgconfig/xwayland.pc
%changelog
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 21.1.1-6
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Tue Jan 16 2024 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-15
Fix for CVE-2023-6816, CVE-2024-0229, CVE-2024-21885, CVE-2024-21886,
CVE-2024-0408, CVE-2024-0409
* Mon Aug 9 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-5
- Backport the latest fixes from Xwayland for EGLstream (rhbz#1977742)
* Wed Dec 13 2023 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-14
- Fix for CVE-2023-6377, CVE-2023-6478
* Tue Jun 22 2021 Mohan Boddu <mboddu@redhat.com> - 21.1.1-4
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Wed Oct 25 2023 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-13
- Fix for CVE-2023-5367
* Mon Jun 21 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-3
* Tue Jun 13 2023 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-12
- Backport fix for a deadlock with DRI3
Resolves: rhbz#2212831
* Fri Mar 31 2023 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-11
- Fix CVE-2023-1393 (#2180298)
* Tue Feb 7 2023 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-10
- Fix CVE-2023-0494 (#2166972)
* Mon Dec 19 2022 Peter Hutterer <peter.hutterer@redhat.com> - 21.1.3-9
- Follow-up fix for CVE-2022-46340 (#2151777)
* Tue Dec 13 2022 Peter Hutterer <peter.hutterer@redhat.com> - 21.1.3-8
- CVE fix for: CVE-2022-4283 (#2151802), CVE-2022-46340 (#2151777),
CVE-2022-46341 (#2151782), CVE-2022-46342 (#2151785),
CVE-2022-46343 (#2151792), CVE-2022-46344 (#2151795)
* Mon Nov 14 2022 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-7
- Fix CVE-2022-3550, CVE-2022-3551
Resolves: rhbz#2140767, rhbz#2140774
* Fri Jul 29 2022 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-6
- CVE fix for: CVE-2022-2319/ZDI-CAN-16062, CVE-2022-2320/ZDI-CAN-16070
Resolves: rhbz#2110442, rhbz#2110437
* Thu Jun 09 2022 Ray Strode <rstrode@redhat.com> - 21.1.3-5
- Rebuild again for ipv6 xtrans fix
Related: #2075132
* Tue May 24 2022 Ray Strode <rstrode@redhat.com> - 21.1.3-3
- Rebuild for ipv6 xtrans fix
Related: #2075132
* Fri Jan 7 2022 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-2
- CVE fix for: CVE-2021-4008 (#2038066), CVE-2021-4009 (#2038068),
CVE-2021-4010 (#2038071), CVE-2021-4011 (#2038073)
* Thu Dec 2 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.3-1
- Rebase to 21.1.3 (rhbz#2015842)
- Prefer EGLstream if both EGLstream and GBM are usable
* Mon Aug 9 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-6
- Backport the latest fixes from Xwayland for EGLstream (rhbz#1977741)
* Tue Jun 29 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-5
- Require libepoxy >= 1.5.5 (rhbz#1976132)
* Mon Jun 21 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-4
- Fix a use-after-free in the previous changes for GLX
* Thu Jun 17 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-2
- Backport fixes for GLX and EGLstream (#1969486)
* Mon Jun 14 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-3
- Backport fixes for GLX and EGLstream (#1961981)
* Thu Jun 17 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-1
- xwayland 21.1.1 (#1952897)
* Thu Jun 03 2021 Tomas Pelka <tpelka@redhat.com> - 21.1.1-2
- bump release and rebuild to correctly trigger gating
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 21.1.0-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Wed Apr 14 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.1-1
- xwayland 21.1.1 (CVE-2021-3472 / ZDI-CAN-1259)
* Thu Mar 18 2021 Olivier Fourdan <ofourdan@redhat.com> - 21.1.0-1
- xwayland 21.1.0