import tigervnc-1.13.1-8.el9_4.3

i9c changed/i9c/tigervnc-1.13.1-8.el9_4.3
MSVSphere Packaging Team 8 months ago
parent f31ef55eb1
commit eb6cef2f9b

@ -0,0 +1,135 @@
diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx
index 6f65e87..3142ba3 100644
--- a/common/rfb/SSecurityPlain.cxx
+++ b/common/rfb/SSecurityPlain.cxx
@@ -27,6 +27,8 @@
#include <rdr/InStream.h>
#if !defined(WIN32) && !defined(__APPLE__)
#include <rfb/UnixPasswordValidator.h>
+#include <unistd.h>
+#include <pwd.h>
#endif
#ifdef WIN32
#include <rfb/WinPasswdValidator.h>
@@ -45,21 +47,22 @@ StringParameter PasswordValidator::plainUsers
bool PasswordValidator::validUser(const char* username)
{
- CharArray users(plainUsers.getValueStr()), user;
+ std::vector<std::string> users;
- while (users.buf) {
- strSplit(users.buf, ',', &user.buf, &users.buf);
-#ifdef WIN32
- if (0 == stricmp(user.buf, "*"))
- return true;
- if (0 == stricmp(user.buf, username))
- return true;
-#else
- if (!strcmp(user.buf, "*"))
- return true;
- if (!strcmp(user.buf, username))
- return true;
+ users = split(plainUsers, ',');
+
+ for (size_t i = 0; i < users.size(); i++) {
+ if (users[i] == "*")
+ return true;
+#if !defined(WIN32) && !defined(__APPLE__)
+ if (users[i] == "%u") {
+ struct passwd *pw = getpwnam(username);
+ if (pw && pw->pw_uid == getuid())
+ return true;
+ }
#endif
+ if (users[i] == username)
+ return true;
}
return false;
}
diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx
index 649eb0b..cce73a0 100644
--- a/common/rfb/util.cxx
+++ b/common/rfb/util.cxx
@@ -99,6 +99,26 @@ namespace rfb {
return false;
}
+ std::vector<std::string> split(const char* src,
+ const char delimiter)
+ {
+ std::vector<std::string> out;
+ const char *start, *stop;
+
+ start = src;
+ do {
+ stop = strchr(start, delimiter);
+ if (stop == NULL) {
+ out.push_back(start);
+ } else {
+ out.push_back(std::string(start, stop-start));
+ start = stop + 1;
+ }
+ } while (stop != NULL);
+
+ return out;
+ }
+
bool strContains(const char* src, char c) {
int l=strlen(src);
for (int i=0; i<l; i++)
diff --git a/common/rfb/util.h b/common/rfb/util.h
index f0ac9ef..ed15c28 100644
--- a/common/rfb/util.h
+++ b/common/rfb/util.h
@@ -27,6 +27,9 @@
#include <limits.h>
#include <string.h>
+#include <string>
+#include <vector>
+
struct timeval;
#ifdef __GNUC__
@@ -76,6 +79,10 @@ namespace rfb {
// that part of the string. Obviously, setting both to 0 is not useful...
bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd=false);
+ // Splits a string with the specified delimiter
+ std::vector<std::string> split(const char* src,
+ const char delimiter);
+
// Returns true if src contains c
bool strContains(const char* src, char c);
diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man
index c36ae34..78db730 100644
--- a/unix/x0vncserver/x0vncserver.man
+++ b/unix/x0vncserver/x0vncserver.man
@@ -125,8 +125,8 @@ parameter instead.
.B \-PlainUsers \fIuser-list\fP
A comma separated list of user names that are allowed to authenticate via
any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP
-to allow any user to authenticate using this security type. Default is to
-deny all users.
+to allow any user to authenticate using this security type. Specify \fB%u\fP
+to allow the user of the server process. Default is to deny all users.
.
.TP
.B \-pam_service \fIname\fP, \-PAMService \fIname\fP
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
index ea87dea..e9fb654 100644
--- a/unix/xserver/hw/vnc/Xvnc.man
+++ b/unix/xserver/hw/vnc/Xvnc.man
@@ -200,8 +200,8 @@ parameter instead.
.B \-PlainUsers \fIuser-list\fP
A comma separated list of user names that are allowed to authenticate via
any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP
-to allow any user to authenticate using this security type. Default is to
-deny all users.
+to allow any user to authenticate using this security type. Specify \fB%u\fP
+to allow the user of the server process. Default is to deny all users.
.
.TP
.B \-pam_service \fIname\fP, \-PAMService \fIname\fP

@ -0,0 +1,17 @@
diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c
index f8141959..c5c36539 100644
--- a/unix/xserver/hw/vnc/xvnc.c
+++ b/unix/xserver/hw/vnc/xvnc.c
@@ -366,8 +366,10 @@ ddxProcessArgument(int argc, char *argv[], int i)
if (strcmp(argv[i], "-inetd") == 0) {
int nullfd;
- dup2(0, 3);
- vncInetdSock = 3;
+ if ((vncInetdSock = dup(0)) == -1)
+ FatalError
+ ("Xvnc error: failed to allocate a new file descriptor for -inetd: %s\n", strerror(errno));
+
/* Avoid xserver >= 1.19's epoll-fd becoming fd 2 / stderr only to be
replaced by /dev/null by OsInit() because the pollfd is not

@ -1,80 +0,0 @@
From a31ba141824a7649e11f0ef7673718ce559d6337 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 1/4] 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>
---
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 6ec419e870..563c4f31a5 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

@ -1,99 +0,0 @@
From 004f461c440cb6611eefb48fbbb4fa53a6d49f80 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Thu, 5 Oct 2023 12:19:45 +1000
Subject: [PATCH xserver 2/4] mi: reset the PointerWindows reference on screen
switch
PointerWindows[] keeps a reference to the last window our sprite
entered - changes are usually handled by CheckMotion().
If we switch between screens via XWarpPointer our
dev->spriteInfo->sprite->win is set to the new screen's root window.
If there's another window at the cursor location CheckMotion() will
trigger the right enter/leave events later. If there is not, it skips
that process and we never trigger LeaveWindow() - PointerWindows[] for
the device still refers to the previous window.
If that window is destroyed we have a dangling reference that will
eventually cause a use-after-free bug when checking the window hierarchy
later.
To trigger this, we require:
- two protocol screens
- XWarpPointer to the other screen's root window
- XDestroyWindow before entering any other window
This is a niche bug so we hack around it by making sure we reset the
PointerWindows[] entry so we cannot have a dangling pointer. This
doesn't handle Enter/Leave events correctly but the previous code didn't
either.
CVE-2023-5380, ZDI-CAN-21608
This vulnerability was discovered by:
Sri working with Trend Micro Zero Day Initiative
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
---
dix/enterleave.h | 2 --
include/eventstr.h | 3 +++
mi/mipointer.c | 17 +++++++++++++++--
3 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/dix/enterleave.h b/dix/enterleave.h
index 4b833d8a3b..e8af924c68 100644
--- a/dix/enterleave.h
+++ b/dix/enterleave.h
@@ -58,8 +58,6 @@ extern void DeviceFocusEvent(DeviceIntPtr dev,
extern void EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode);
-extern void LeaveWindow(DeviceIntPtr dev);
-
extern void CoreFocusEvent(DeviceIntPtr kbd,
int type, int mode, int detail, WindowPtr pWin);
diff --git a/include/eventstr.h b/include/eventstr.h
index bf3b95fe4a..2bae3b0767 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -296,4 +296,7 @@ union _InternalEvent {
#endif
};
+extern void
+LeaveWindow(DeviceIntPtr dev);
+
#endif
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 75be1aeeb8..b12ae9be1d 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -397,8 +397,21 @@ miPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
#ifdef PANORAMIX
&& noPanoramiXExtension
#endif
- )
- UpdateSpriteForScreen(pDev, pScreen);
+ ) {
+ DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
+ /* Hack for CVE-2023-5380: if we're moving
+ * screens PointerWindows[] keeps referring to the
+ * old window. If that gets destroyed we have a UAF
+ * bug later. Only happens when jumping from a window
+ * to the root window on the other screen.
+ * Enter/Leave events are incorrect for that case but
+ * too niche to fix.
+ */
+ LeaveWindow(pDev);
+ if (master)
+ LeaveWindow(master);
+ UpdateSpriteForScreen(pDev, pScreen);
+ }
}
/**
--
2.41.0

@ -1,74 +0,0 @@
From 0c1a93d319558fe3ab2d94f51d174b4f93810afd 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] 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
---
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 dcd4efb3bc..54ea11a938 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 b063128df0..3f3224d626 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2539,6 +2539,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,
@@ -2549,6 +2551,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));
--
GitLab

@ -1,59 +0,0 @@
From 3e0222fcae552685d423914a683c1709dc5f6d6b 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-XXXXX, ZDI-CAN-22561
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
---
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 25469f57b2..c4fef8a1f6 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 b79c17f9bf..90c5a9a933 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

@ -1,51 +0,0 @@
From 77e294797db17845808462b588d4e7a2130196bc 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] 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
---
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 5b77b1a444..2b05ac5f39 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 867ec74363..ded8679d76 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

@ -1,84 +0,0 @@
From 45ea0a93934c8a3760a4d68ba4ffc932375f60de 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 1/2] 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
---
dix/enterleave.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index ded8679d76..17964b00a4 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

@ -1,216 +0,0 @@
From 4c7a16b089b721b9c07f4ed593deba4f22158dbf 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 2/2] 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
---
dix/enterleave.c | 119 ++++++++++++++++++++---------------------------
1 file changed, 51 insertions(+), 68 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index 17964b00a4..7b7ba1098b 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->valuator5 = v->axisVal[first + 5];
+ case 5:
+ ev->valuator4 = v->axisVal[first + 4];
+ case 4:
+ ev->valuator3 = 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);
+ BUG_RETURN(evcount <= ARRAY_SIZE(sev));
- 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;
- }
+ 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

@ -1,37 +0,0 @@
From 061eb684996627347acdf87ec11d108cedee71b6 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] 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
---
Xi/exevents.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 54ea11a938..e161714682 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

@ -0,0 +1,32 @@
From 133e0d651c5d12bf01999d6289e84e224ba77adc Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 22 Jan 2024 14:22:12 +1000
Subject: [PATCH] dix: fix valuator copy/paste error in the DeviceStateNotify
event
Fixes 219c54b8a3337456ce5270ded6a67bcde53553d5
---
dix/enterleave.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index 7b7ba1098b..c1e6ac600e 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -619,11 +619,11 @@ FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
ev->first_valuator = first;
switch (ev->num_valuators) {
case 6:
- ev->valuator2 = v->axisVal[first + 5];
+ ev->valuator5 = v->axisVal[first + 5];
case 5:
- ev->valuator2 = v->axisVal[first + 4];
+ ev->valuator4 = v->axisVal[first + 4];
case 4:
- ev->valuator2 = v->axisVal[first + 3];
+ ev->valuator3 = v->axisVal[first + 3];
case 3:
ev->valuator2 = v->axisVal[first + 2];
case 2:
--
GitLab

@ -1,109 +0,0 @@
From a483b5c7724469309e3df427730cbb8b805b9c9f 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] 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
---
Xi/xichangehierarchy.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
index 01eb7a8af4..67eedddec6 100644
--- a/Xi/xichangehierarchy.c
+++ b/Xi/xichangehierarchy.c
@@ -340,6 +340,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);
@@ -389,8 +394,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = add_master(client, c, flags);
if (rc != Success)
goto unwind;
- }
+ changes = FLUSH;
break;
+ }
case XIRemoveMaster:
{
xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any;
@@ -399,8 +405,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = remove_master(client, r, flags);
if (rc != Success)
goto unwind;
- }
+ changes = FLUSH;
break;
+ }
case XIDetachSlave:
{
xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any;
@@ -409,8 +416,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

@ -1,70 +0,0 @@
From 4e0e99ef60f07757756913221847a26c71afc3e8 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] 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
---
dix/devices.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/dix/devices.c b/dix/devices.c
index 3f3224d62..3a64d8702 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -451,14 +451,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);
@@ -509,6 +515,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

@ -1,53 +0,0 @@
From 1a5e3c3e68d4f965077ea6a40ba57cc0d5a4e8cb 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] 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
---
dix/devices.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/dix/devices.c b/dix/devices.c
index c7fa8fad69..87f4d4a213 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -482,6 +482,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) {
@@ -1088,6 +1095,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

@ -0,0 +1,45 @@
From 96798fc1967491c80a4d0c8d9e0a80586cb2152b Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 22 Mar 2024 18:51:45 -0700
Subject: [PATCH 1/4] Xi: ProcXIGetSelectedEvents needs to use unswapped length
to send reply
CVE-2024-31080
Reported-by: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=69762
Fixes: 53e821ab4 ("Xi: add request processing for XIGetSelectedEvents.")
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1463>
---
Xi/xiselectev.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c
index edcb8a0d3..ac1494987 100644
--- a/Xi/xiselectev.c
+++ b/Xi/xiselectev.c
@@ -349,6 +349,7 @@ ProcXIGetSelectedEvents(ClientPtr client)
InputClientsPtr others = NULL;
xXIEventMask *evmask = NULL;
DeviceIntPtr dev;
+ uint32_t length;
REQUEST(xXIGetSelectedEventsReq);
REQUEST_SIZE_MATCH(xXIGetSelectedEventsReq);
@@ -418,10 +419,12 @@ ProcXIGetSelectedEvents(ClientPtr client)
}
}
+ /* save the value before SRepXIGetSelectedEvents swaps it */
+ length = reply.length;
WriteReplyToClient(client, sizeof(xXIGetSelectedEventsReply), &reply);
if (reply.num_masks)
- WriteToClient(client, reply.length * 4, buffer);
+ WriteToClient(client, length * 4, buffer);
free(buffer);
return Success;
--
2.44.0

@ -0,0 +1,43 @@
From 3e77295f888c67fc7645db5d0c00926a29ffecee Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 22 Mar 2024 18:56:27 -0700
Subject: [PATCH 2/4] Xi: ProcXIPassiveGrabDevice needs to use unswapped length
to send reply
CVE-2024-31081
Fixes: d220d6907 ("Xi: add GrabButton and GrabKeysym code.")
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1463>
---
Xi/xipassivegrab.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index c9ac2f855..896233bec 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -93,6 +93,7 @@ ProcXIPassiveGrabDevice(ClientPtr client)
GrabParameters param;
void *tmp;
int mask_len;
+ uint32_t length;
REQUEST(xXIPassiveGrabDeviceReq);
REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
@@ -247,9 +248,11 @@ ProcXIPassiveGrabDevice(ClientPtr client)
}
}
+ /* save the value before SRepXIPassiveGrabDevice swaps it */
+ length = rep.length;
WriteReplyToClient(client, sizeof(rep), &rep);
if (rep.num_modifiers)
- WriteToClient(client, rep.length * 4, modifiers_failed);
+ WriteToClient(client, length * 4, modifiers_failed);
out:
free(modifiers_failed);
--
2.44.0

@ -0,0 +1,47 @@
From 6c684d035c06fd41c727f0ef0744517580864cef Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 22 Mar 2024 19:07:34 -0700
Subject: [PATCH 3/4] Xquartz: ProcAppleDRICreatePixmap needs to use unswapped
length to send reply
CVE-2024-31082
Fixes: 14205ade0 ("XQuartz: appledri: Fix byte swapping in replies")
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1463>
---
hw/xquartz/xpr/appledri.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/xquartz/xpr/appledri.c b/hw/xquartz/xpr/appledri.c
index 77574655b..40422b61a 100644
--- a/hw/xquartz/xpr/appledri.c
+++ b/hw/xquartz/xpr/appledri.c
@@ -272,6 +272,7 @@ ProcAppleDRICreatePixmap(ClientPtr client)
xAppleDRICreatePixmapReply rep;
int width, height, pitch, bpp;
void *ptr;
+ CARD32 stringLength;
REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq);
@@ -307,6 +308,7 @@ ProcAppleDRICreatePixmap(ClientPtr client)
if (sizeof(rep) != sz_xAppleDRICreatePixmapReply)
ErrorF("error sizeof(rep) is %zu\n", sizeof(rep));
+ stringLength = rep.stringLength; /* save unswapped value */
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
@@ -319,7 +321,7 @@ ProcAppleDRICreatePixmap(ClientPtr client)
}
WriteToClient(client, sizeof(rep), &rep);
- WriteToClient(client, rep.stringLength, path);
+ WriteToClient(client, stringLength, path);
return Success;
}
--
2.44.0

@ -0,0 +1,72 @@
From 337d8d48b618d4fc0168a7b978be4c3447650b04 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 5 Apr 2024 15:24:49 +0200
Subject: [PATCH] render: Avoid possible double-free in ProcRenderAddGlyphs()
ProcRenderAddGlyphs() adds the glyph to the glyphset using AddGlyph() and
then frees it using FreeGlyph() to decrease the reference count, after
AddGlyph() has increased it.
AddGlyph() however may chose to reuse an existing glyph if it's already
in the glyphSet, and free the glyph that was given, in which case the
caller function, ProcRenderAddGlyphs() will call FreeGlyph() on an
already freed glyph, as reported by ASan:
READ of size 4 thread T0
#0 in FreeGlyph xserver/render/glyph.c:252
#1 in ProcRenderAddGlyphs xserver/render/render.c:1174
#2 in Dispatch xserver/dix/dispatch.c:546
#3 in dix_main xserver/dix/main.c:271
#4 in main xserver/dix/stubmain.c:34
#5 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#6 in __libc_start_main_impl ../csu/libc-start.c:360
#7 (/usr/bin/Xwayland+0x44fe4)
Address is located 0 bytes inside of 64-byte region
freed by thread T0 here:
#0 in __interceptor_free libsanitizer/asan/asan_malloc_linux.cpp:52
#1 in _dixFreeObjectWithPrivates xserver/dix/privates.c:538
#2 in AddGlyph xserver/render/glyph.c:295
#3 in ProcRenderAddGlyphs xserver/render/render.c:1173
#4 in Dispatch xserver/dix/dispatch.c:546
#5 in dix_main xserver/dix/main.c:271
#6 in main xserver/dix/stubmain.c:34
#7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
previously allocated by thread T0 here:
#0 in __interceptor_malloc libsanitizer/asan/asan_malloc_linux.cpp:69
#1 in AllocateGlyph xserver/render/glyph.c:355
#2 in ProcRenderAddGlyphs xserver/render/render.c:1085
#3 in Dispatch xserver/dix/dispatch.c:546
#4 in dix_main xserver/dix/main.c:271
#5 in main xserver/dix/stubmain.c:34
#6 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: heap-use-after-free xserver/render/glyph.c:252 in FreeGlyph
To avoid that, make sure not to free the given glyph in AddGlyph().
v2: Simplify the test using the boolean returned from AddGlyph() (Michel)
v3: Simplify even more by not freeing the glyph in AddGlyph() (Peter)
Fixes: bdca6c3d1 - render: fix refcounting of glyphs during ProcRenderAddGlyphs
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1659
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1476>
---
render/glyph.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/render/glyph.c b/render/glyph.c
index 13991f8a1..5fa7f3b5b 100644
--- a/render/glyph.c
+++ b/render/glyph.c
@@ -291,8 +291,6 @@ AddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature,
TRUE, glyph->sha1);
if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) {
- FreeGlyphPicture(glyph);
- dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
glyph = gr->glyph;
}
else if (gr->glyph != glyph) {
--
2.44.0

@ -0,0 +1,112 @@
From bdca6c3d1f5057eeb31609b1280fc93237b00c77 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 30 Jan 2024 13:13:35 +1000
Subject: [PATCH 4/4] render: fix refcounting of glyphs during
ProcRenderAddGlyphs
Previously, AllocateGlyph would return a new glyph with refcount=0 and a
re-used glyph would end up not changing the refcount at all. The
resulting glyph_new array would thus have multiple entries pointing to
the same non-refcounted glyphs.
AddGlyph may free a glyph, resulting in a UAF when the same glyph
pointer is then later used.
Fix this by returning a refcount of 1 for a new glyph and always
incrementing the refcount for a re-used glyph, followed by dropping that
refcount back down again when we're done with it.
CVE-2024-31083, ZDI-CAN-22880
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1463>
---
render/glyph.c | 5 +++--
render/glyphstr_priv.h | 1 +
render/render.c | 15 +++++++++++----
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/render/glyph.c b/render/glyph.c
index 850ea8440..13991f8a1 100644
--- a/render/glyph.c
+++ b/render/glyph.c
@@ -245,10 +245,11 @@ FreeGlyphPicture(GlyphPtr glyph)
}
}
-static void
+void
FreeGlyph(GlyphPtr glyph, int format)
{
CheckDuplicates(&globalGlyphs[format], "FreeGlyph");
+ BUG_RETURN(glyph->refcnt == 0);
if (--glyph->refcnt == 0) {
GlyphRefPtr gr;
int i;
@@ -354,7 +355,7 @@ AllocateGlyph(xGlyphInfo * gi, int fdepth)
glyph = (GlyphPtr) malloc(size);
if (!glyph)
return 0;
- glyph->refcnt = 0;
+ glyph->refcnt = 1;
glyph->size = size + sizeof(xGlyphInfo);
glyph->info = *gi;
dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH);
diff --git a/render/glyphstr.h b/render/glyphstr.h
index 2f51bd244..3b1d806d1 100644
--- a/render/glyphstr.h
+++ b/render/glyphstr.h
@@ -108,6 +108,7 @@ extern Bool
extern GlyphPtr FindGlyph(GlyphSetPtr glyphSet, Glyph id);
extern GlyphPtr AllocateGlyph(xGlyphInfo * gi, int format);
+extern void FreeGlyph(GlyphPtr glyph, int format);
extern Bool
ResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change);
diff --git a/render/render.c b/render/render.c
index 29c5055c6..fe5e37dd9 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1076,6 +1076,7 @@ ProcRenderAddGlyphs(ClientPtr client)
if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph) {
glyph_new->found = TRUE;
+ ++glyph_new->glyph->refcnt;
}
else {
GlyphPtr glyph;
@@ -1168,8 +1169,10 @@ ProcRenderAddGlyphs(ClientPtr client)
err = BadAlloc;
goto bail;
}
- for (i = 0; i < nglyphs; i++)
+ for (i = 0; i < nglyphs; i++) {
AddGlyph(glyphSet, glyphs[i].glyph, glyphs[i].id);
+ FreeGlyph(glyphs[i].glyph, glyphSet->fdepth);
+ }
if (glyphsBase != glyphsLocal)
free(glyphsBase);
@@ -1179,9 +1182,13 @@ ProcRenderAddGlyphs(ClientPtr client)
FreePicture((void *) pSrc, 0);
if (pSrcPix)
FreeScratchPixmapHeader(pSrcPix);
- for (i = 0; i < nglyphs; i++)
- if (glyphs[i].glyph && !glyphs[i].found)
- free(glyphs[i].glyph);
+ for (i = 0; i < nglyphs; i++) {
+ if (glyphs[i].glyph) {
+ --glyphs[i].glyph->refcnt;
+ if (!glyphs[i].found)
+ free(glyphs[i].glyph);
+ }
+ }
if (glyphsBase != glyphsLocal)
free(glyphsBase);
return err;
--
2.44.0

@ -1,77 +0,0 @@
From 1801fe0ac3926882d47d7e1ad6c0518a2cdffd41 Mon Sep 17 00:00:00 2001
From: Povilas Kanapickas <povilas@radix.lt>
Date: Sun, 19 Dec 2021 18:11:07 +0200
Subject: [PATCH] dix: Fix use after free in input device shutdown
This fixes access to freed heap memory via dev->master. E.g. when
running BarrierNotify.ReceivesNotifyEvents/7 test from
xorg-integration-tests:
==24736==ERROR: AddressSanitizer: heap-use-after-free on address
0x619000065020 at pc 0x55c450e2b9cf bp 0x7fffc532fd20 sp 0x7fffc532fd10
READ of size 4 at 0x619000065020 thread T0
#0 0x55c450e2b9ce in GetMaster ../../../dix/devices.c:2722
#1 0x55c450e9d035 in IsFloating ../../../dix/events.c:346
#2 0x55c4513209c6 in GetDeviceUse ../../../Xi/xiquerydevice.c:525
../../../Xi/xichangehierarchy.c:95
#4 0x55c450e3455c in RemoveDevice ../../../dix/devices.c:1204
../../../hw/xfree86/common/xf86Xinput.c:1142
#6 0x55c450e17b04 in CloseDeviceList ../../../dix/devices.c:1038
#7 0x55c450e1de85 in CloseDownDevices ../../../dix/devices.c:1068
#8 0x55c450e837ef in dix_main ../../../dix/main.c:302
#9 0x55c4517a8d93 in main ../../../dix/stubmain.c:34
(/lib/x86_64-linux-gnu/libc.so.6+0x28564)
#11 0x55c450d0113d in _start (/usr/lib/xorg/Xorg+0x117713d)
0x619000065020 is located 160 bytes inside of 912-byte region
[0x619000064f80,0x619000065310)
freed by thread T0 here:
(/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf)
#1 0x55c450e19f1c in CloseDevice ../../../dix/devices.c:1014
#2 0x55c450e343a4 in RemoveDevice ../../../dix/devices.c:1186
../../../hw/xfree86/common/xf86Xinput.c:1142
#4 0x55c450e17b04 in CloseDeviceList ../../../dix/devices.c:1038
#5 0x55c450e1de85 in CloseDownDevices ../../../dix/devices.c:1068
#6 0x55c450e837ef in dix_main ../../../dix/main.c:302
#7 0x55c4517a8d93 in main ../../../dix/stubmain.c:34
(/lib/x86_64-linux-gnu/libc.so.6+0x28564)
previously allocated by thread T0 here:
(/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10ddc6)
#1 0x55c450e1c57b in AddInputDevice ../../../dix/devices.c:259
#2 0x55c450e34840 in AllocDevicePair ../../../dix/devices.c:2755
#3 0x55c45130318f in add_master ../../../Xi/xichangehierarchy.c:152
../../../Xi/xichangehierarchy.c:465
#5 0x55c4512cb9f5 in ProcIDispatch ../../../Xi/extinit.c:390
#6 0x55c450e6a92b in Dispatch ../../../dix/dispatch.c:551
#7 0x55c450e834b7 in dix_main ../../../dix/main.c:272
#8 0x55c4517a8d93 in main ../../../dix/stubmain.c:34
(/lib/x86_64-linux-gnu/libc.so.6+0x28564)
The problem is caused by dev->master being not reset when disabling the
device, which then causes dangling pointer when the master device itself
is being deleted when exiting whole server.
Note that RecalculateMasterButtons() requires dev->master to be still
valid, so we can reset it only at the end of function.
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
---
dix/devices.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dix/devices.c b/dix/devices.c
index e62c34c55..5f9ce1678 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -520,6 +520,7 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
}
RecalculateMasterButtons(dev);
+ dev->master = NULL;
return TRUE;
}
--
2.43.0

@ -5,7 +5,7 @@
Name: tigervnc
Version: 1.13.1
Release: 3%{?dist}.6
Release: 8%{?dist}.3
Summary: A TigerVNC remote display system
%global _hardened_build 1
@ -26,30 +26,26 @@ Patch1: tigervnc-use-gnome-as-default-session.patch
Patch2: tigervnc-vncsession-restore-script-systemd-service.patch
# Upstream patches
Patch50: tigervnc-support-username-alias-in-plainusers.patch
Patch51: tigervnc-use-dup-to-get-available-fd-for-inetd.patch
# Upstreamable patches
Patch50: tigervnc-dont-get-pointer-position-for-floating-device.patch
Patch80: tigervnc-dont-get-pointer-position-for-floating-device.patch
# This is tigervnc-%%{version}/unix/xserver116.patch rebased on the latest xorg
Patch100: tigervnc-xserver120.patch
# 1326867 - [RHEL7.3] GLX applications in an Xvnc session fails to start
Patch101: 0001-rpath-hack.patch
# Xorg CVEs
Patch200: xorg-CVE-2023-5367.patch
Patch201: xorg-CVE-2023-5380.patch
Patch202: xorg-CVE-2023-6377.patch
Patch203: xorg-CVE-2023-6478.patch
Patch204: xorg-CVE-2023-6816.patch
Patch205: xorg-CVE-2024-0229-1.patch
Patch206: xorg-CVE-2024-0229-2.patch
Patch207: xorg-CVE-2024-0229-3.patch
Patch208: xorg-CVE-2024-21885.patch
Patch209: xorg-CVE-2024-21886-1.patch
Patch210: xorg-CVE-2024-21886-2.patch
# Related to CVE-2024-21886
Patch211: xorg-dix-fix-use-after-free-in-input-device-shutdown.patch
# XServer patches
# CVE-2024-0229
# https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1251
Patch200: xorg-CVE-2024-0229-followup.patch
Patch201: xorg-CVE-2024-31080.patch
Patch202: xorg-CVE-2024-31081.patch
Patch203: xorg-CVE-2024-31082.patch
Patch204: xorg-CVE-2024-31083.patch
Patch205: xorg-CVE-2024-31083-followup.patch
BuildRequires: make
BuildRequires: gcc-c++
@ -175,20 +171,15 @@ This package contains icons for TigerVNC viewer
%package selinux
Summary: SELinux module for TigerVNC
BuildArch: noarch
BuildRequires: pkgconfig(systemd)
BuildRequires: selinux-policy
BuildRequires: selinux-policy-devel
# Required for restorecon
Requires: policycoreutils
# Required for matchpathcon
Requires: libselinux-utils
Requires: selinux-policy
Requires: selinux-policy-%{selinuxtype}
Requires(post): selinux-policy-base
Requires(post): selinux-policy-%{selinuxtype}
Requires(post): libselinux-utils
Requires(post): policycoreutils
Requires(post): policycoreutils-python-utils
BuildRequires: selinux-policy-devel
# Required for matchpathcon
Requires: libselinux-utils
# Required for restorecon
Requires: policycoreutils
%{?selinux_requires}
%description selinux
This package provides the SELinux policy module to ensure TigerVNC
@ -204,27 +195,23 @@ for all in `find . -type f -perm -001`; do
done
%patch100 -p1 -b .xserver120-rebased
%patch101 -p1 -b .rpath
%patch200 -p1 -b .xorg-CVE-2023-5367
%patch201 -p1 -b .xorg-CVE-2023-5380
%patch202 -p1 -b .xorg-CVE-2023-6377
%patch203 -p1 -b .xorg-CVE-2023-6478
%patch204 -p1 -b .xorg-CVE-2023-6816
%patch205 -p1 -b .xorg-CVE-2024-0229-1
%patch206 -p1 -b .xorg-CVE-2024-0229-2
%patch207 -p1 -b .xorg-CVE-2024-0229-3
%patch208 -p1 -b .xorg-CVE-2024-21885
%patch209 -p1 -b .xorg-CVE-2024-21886-1
%patch210 -p1 -b .xorg-CVE-2024-21886-2
%patch211 -p1 -b .xorg-dix-fix-use-after-free-in-input-device-shutdown
%patch200 -p1 -b .xorg-CVE-2024-0229-followup
%patch201 -p1 -b .xorg-CVE-2024-31080.patch
%patch202 -p1 -b .xorg-CVE-2024-31081.patch
%patch203 -p1 -b .xorg-CVE-2024-31082.patch
%patch204 -p1 -b .xorg-CVE-2024-31083.patch
%patch205 -p1 -b .xorg-CVE-2024-31083-followup
popd
%patch1 -p1 -b .use-gnome-as-default-session
%patch2 -p1 -b .vncsession-restore-script-systemd-service
# Upstream patches
%patch50 -p1 -b .support-username-alias-in-plainusers
%patch51 -p1 -b .use-dup-to-get-available-fd-for-inetd
# Upstreamable patches
%patch50 -p1 -b .dont-get-pointer-position-for-floating-device
%patch80 -p1 -b .dont-get-pointer-position-for-floating-device
%build
%ifarch sparcv9 sparc64 s390 s390x
@ -407,45 +394,55 @@ fi
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
%changelog
* Thu Jan 25 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3.6
- Fix use after free related to CVE-2024-21886
Resolves: RHEL-20435
* Mon Apr 22 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-8.3
- Rebuild (z-stream target)
Resolves: RHEL-30985
Resolves: RHEL-31015
* Fri Apr 12 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-8.2
- Fix crash caused by fix for CVE-2024-31083
Resolves: RHEL-30985
* Thu Apr 04 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-8.1
- Fix CVE-2024-31080 tigervnc: xorg-x11-server: Heap buffer overread/data leakage in ProcXIGetSelectedEvents
Resolves: RHEL-31015
- Fix CVE-2024-31083 tigervnc: xorg-x11-server: User-after-free in ProcRenderAddGlyphs
Resolves: RHEL-30985
* Wed Feb 07 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-8
- Fix copy/paste error in the DeviceStateNotify
Resolves: RHEL-20586
* Fri Jan 19 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3.5
- Don't try to get pointer position when the pointer becomes a floating device
Resolves: RHEL-20435
Resolves: RHEL-20533
* Fri Jan 12 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3.4
* Mon Jan 22 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-7
- Fix CVE-2024-21886 tigervnc: xorg-x11-server: heap buffer overflow in DisableDevice
Resolves: RHEL-20435
Resolves: RHEL-20389
- Fix CVE-2024-21885 tigervnc: xorg-x11-server: heap buffer overflow in XISendDeviceHierarchyEvent
Resolves: RHEL-20424
Resolves: RHEL-20383
- Fix CVE-2024-0229 tigervnc: xorg-x11-server: reattaching to different master device may lead to out-of-bounds memory access
Resolves: RHEL-20586
Resolves: RHEL-20533
- Fix CVE-2023-6816 tigervnc: xorg-x11-server: Heap buffer overflow in DeviceFocusEvent and ProcXIQueryPointer
Resolves: RHEL-21247
Resolves: RHEL-21213
* Wed Dec 13 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3.3
- Updated fix for CVE-2023-6377 tigervnc: xorg-x11-server: out-of-bounds memory reads/writes in XKB button actions
Resolves: RHEL-18413
* Mon Jan 08 2024 Jan Grulich <jgrulich@redhat.com> - 1.13.1-6
- Use dup() to get available file descriptor when using -inetd option
Resolves: RHEL-19858
* Mon Dec 11 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3.2
- Rebuild (selinux-policy)
Resolves: RHEL-18413
Resolves: RHEL-18425
* Thu Dec 07 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3.1
* Mon Dec 18 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-5
- Fix CVE-2023-6377 tigervnc: xorg-x11-server: out-of-bounds memory reads/writes in XKB button actions
Resolves: RHEL-18413
Resolves: RHEL-18414
- Fix CVE-2023-6478 tigervnc: xorg-x11-server: out-of-bounds memory read in RRChangeOutputProperty and RRChangeProviderProperty
Resolves: RHEL-18425
Resolves: RHEL-18426
* Thu Nov 02 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3
* Wed Nov 01 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-4
- Fix CVE-2023-5380 tigervnc: xorg-x11-server: Use-after-free bug in DestroyWindow
Resolves: RHEL-15237
- Fix CVE-2023-5367 tigervnc: xorg-x11-server: Out-of-bounds write in XIChangeDeviceProperty/RRChangeOutputProperty
Resolves: RHEL-15233
Resolves: RHEL-15249
* Mon Oct 09 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-3
- Support username alias in PlainUsers
Resolves: RHEL-8430
* Tue Apr 11 2023 Jan Grulich <jgrulich@redhat.com> - 1.13.1-2
- xorg-x11-server: X.Org Server Overlay Window Use-After-Free Local Privilege

Loading…
Cancel
Save