import OL tigervnc-1.15.0-6.el9_7

This commit is contained in:
eabdullin 2025-11-27 12:02:05 +00:00
parent e8b0b05a55
commit d6a06c9d8d
20 changed files with 225 additions and 1279 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/tigervnc-1.14.1.tar.gz
SOURCES/tigervnc-1.15.0.tar.gz

View File

@ -1 +1 @@
bc3c8bc9f454eb307011cd5965251f4a28040a25 SOURCES/tigervnc-1.14.1.tar.gz
fec424f110bdf5032cd5eb4df2596b8251d2e1ed SOURCES/tigervnc-1.15.0.tar.gz

View File

@ -1,543 +0,0 @@
From c23be952f50ba34c49134b6280ce503f154dc9bc Mon Sep 17 00:00:00 2001
From: Gaurav Ujjwal <gujjwal00@gmail.com>
Date: Wed, 25 Sep 2024 21:21:26 +0530
Subject: [PATCH] Add clipboard support to x0vncserver
---
unix/tx/TXWindow.cxx | 13 ++-
unix/tx/TXWindow.h | 3 +-
unix/x0vncserver/CMakeLists.txt | 1 +
unix/x0vncserver/XDesktop.cxx | 49 +++++++-
unix/x0vncserver/XDesktop.h | 13 ++-
unix/x0vncserver/XSelection.cxx | 195 +++++++++++++++++++++++++++++++
unix/x0vncserver/XSelection.h | 58 +++++++++
unix/x0vncserver/x0vncserver.cxx | 5 -
unix/x0vncserver/x0vncserver.man | 21 ++++
9 files changed, 344 insertions(+), 14 deletions(-)
create mode 100644 unix/x0vncserver/XSelection.cxx
create mode 100644 unix/x0vncserver/XSelection.h
diff --git a/unix/tx/TXWindow.cxx b/unix/tx/TXWindow.cxx
index ee097e4..b10ed84 100644
--- a/unix/tx/TXWindow.cxx
+++ b/unix/tx/TXWindow.cxx
@@ -36,7 +36,7 @@ std::list<TXWindow*> windows;
Atom wmProtocols, wmDeleteWindow, wmTakeFocus;
Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;
-Atom xaCLIPBOARD;
+Atom xaCLIPBOARD, xaUTF8_STRING, xaINCR;
unsigned long TXWindow::black, TXWindow::white;
unsigned long TXWindow::defaultFg, TXWindow::defaultBg;
unsigned long TXWindow::lightBg, TXWindow::darkBg;
@@ -65,6 +65,8 @@ void TXWindow::init(Display* dpy, const char* defaultWindowClass_)
xaSELECTION_TIME = XInternAtom(dpy, "SELECTION_TIME", False);
xaSELECTION_STRING = XInternAtom(dpy, "SELECTION_STRING", False);
xaCLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False);
+ xaUTF8_STRING = XInternAtom(dpy, "UTF8_STRING", False);
+ xaINCR = XInternAtom(dpy, "INCR", False);
XColor cols[6];
cols[0].red = cols[0].green = cols[0].blue = 0x0000;
cols[1].red = cols[1].green = cols[1].blue = 0xbbbb;
@@ -462,17 +464,18 @@ void TXWindow::handleXEvent(XEvent* ev)
} else {
se.property = ev->xselectionrequest.property;
if (se.target == xaTARGETS) {
- Atom targets[2];
+ Atom targets[3];
targets[0] = xaTIMESTAMP;
targets[1] = XA_STRING;
+ targets[2] = xaUTF8_STRING;
XChangeProperty(dpy, se.requestor, se.property, XA_ATOM, 32,
- PropModeReplace, (unsigned char*)targets, 2);
+ PropModeReplace, (unsigned char*)targets, 3);
} else if (se.target == xaTIMESTAMP) {
Time t = selectionOwnTime[se.selection];
XChangeProperty(dpy, se.requestor, se.property, XA_INTEGER, 32,
PropModeReplace, (unsigned char*)&t, 1);
- } else if (se.target == XA_STRING) {
- if (!selectionRequest(se.requestor, se.selection, se.property))
+ } else if (se.target == XA_STRING || se.target == xaUTF8_STRING) {
+ if (!selectionRequest(se.requestor, se.selection, se.target, se.property))
se.property = None;
} else {
se.property = None;
diff --git a/unix/tx/TXWindow.h b/unix/tx/TXWindow.h
index 223c07a..32ae9a3 100644
--- a/unix/tx/TXWindow.h
+++ b/unix/tx/TXWindow.h
@@ -155,6 +155,7 @@ public:
// returning true if successful, false otherwise.
virtual bool selectionRequest(Window /*requestor*/,
Atom /*selection*/,
+ Atom /*target*/,
Atom /*property*/) { return false;}
// Static methods
@@ -224,6 +225,6 @@ private:
extern Atom wmProtocols, wmDeleteWindow, wmTakeFocus;
extern Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;
-extern Atom xaCLIPBOARD;
+extern Atom xaCLIPBOARD, xaUTF8_STRING, xaINCR;
#endif
diff --git a/unix/x0vncserver/CMakeLists.txt b/unix/x0vncserver/CMakeLists.txt
index 5ce9577..9d6d213 100644
--- a/unix/x0vncserver/CMakeLists.txt
+++ b/unix/x0vncserver/CMakeLists.txt
@@ -11,6 +11,7 @@ add_executable(x0vncserver
XPixelBuffer.cxx
XDesktop.cxx
RandrGlue.c
+ XSelection.cxx
../vncconfig/QueryConnectDialog.cxx
)
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
index 1e52987..db5b6ae 100644
--- a/unix/x0vncserver/XDesktop.cxx
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -43,6 +43,7 @@
#endif
#ifdef HAVE_XFIXES
#include <X11/extensions/Xfixes.h>
+#include <X11/Xatom.h>
#endif
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
@@ -81,7 +82,7 @@ static const char * ledNames[XDESKTOP_N_LEDS] = {
XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
: dpy(dpy_), geometry(geometry_), pb(0), server(0),
- queryConnectDialog(0), queryConnectSock(0),
+ queryConnectDialog(0), queryConnectSock(0), selection(dpy_, this),
oldButtonMask(0), haveXtest(false), haveDamage(false),
maxButtons(0), running(false), ledMasks(), ledState(0),
codeMap(0), codeMapLen(0)
@@ -179,10 +180,15 @@ XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
if (XFixesQueryExtension(dpy, &xfixesEventBase, &xfixesErrorBase)) {
XFixesSelectCursorInput(dpy, DefaultRootWindow(dpy),
XFixesDisplayCursorNotifyMask);
+
+ XFixesSelectSelectionInput(dpy, DefaultRootWindow(dpy), XA_PRIMARY,
+ XFixesSetSelectionOwnerNotifyMask);
+ XFixesSelectSelectionInput(dpy, DefaultRootWindow(dpy), xaCLIPBOARD,
+ XFixesSetSelectionOwnerNotifyMask);
} else {
#endif
vlog.info("XFIXES extension not present");
- vlog.info("Will not be able to display cursors");
+ vlog.info("Will not be able to display cursors or monitor clipboard");
#ifdef HAVE_XFIXES
}
#endif
@@ -892,6 +898,20 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) {
return false;
return setCursor();
+ }
+ else if (ev->type == xfixesEventBase + XFixesSelectionNotify) {
+ XFixesSelectionNotifyEvent* sev = (XFixesSelectionNotifyEvent*)ev;
+
+ if (!running)
+ return true;
+
+ if (sev->subtype != XFixesSetSelectionOwnerNotify)
+ return false;
+
+ selection.handleSelectionOwnerChange(sev->owner, sev->selection,
+ sev->timestamp);
+
+ return true;
#endif
#ifdef HAVE_XRANDR
} else if (ev->type == Expose) {
@@ -1039,3 +1059,28 @@ bool XDesktop::setCursor()
return true;
}
#endif
+
+// X selection availability changed, let VNC clients know
+void XDesktop::handleXSelectionAnnounce(bool available) {
+ server->announceClipboard(available);
+}
+
+// A VNC client wants data, send request to selection owner
+void XDesktop::handleClipboardRequest() {
+ selection.requestSelectionData();
+}
+
+// Data is available, send it to clients
+void XDesktop::handleXSelectionData(const char* data) {
+ server->sendClipboardData(data);
+}
+
+// When a client says it has clipboard data, request it
+void XDesktop::handleClipboardAnnounce(bool available) {
+ if(available) server->requestClipboard();
+}
+
+// Client has sent the data
+void XDesktop::handleClipboardData(const char* data) {
+ if (data) selection.handleClientClipboardData(data);
+}
diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h
index 4777a65..bc8d2a9 100644
--- a/unix/x0vncserver/XDesktop.h
+++ b/unix/x0vncserver/XDesktop.h
@@ -32,6 +32,8 @@
#include <vncconfig/QueryConnectDialog.h>
+#include "XSelection.h"
+
class Geometry;
class XPixelBuffer;
@@ -46,7 +48,8 @@ struct AddedKeySym
class XDesktop : public rfb::SDesktop,
public TXGlobalEventHandler,
- public QueryResultCallback
+ public QueryResultCallback,
+ public XSelectionHandler
{
public:
XDesktop(Display* dpy_, Geometry *geometry);
@@ -65,6 +68,13 @@ public:
virtual void clientCutText(const char* str);
virtual unsigned int setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout);
+ void handleClipboardRequest() override;
+ void handleClipboardAnnounce(bool available) override;
+ void handleClipboardData(const char* data) override;
+
+ // -=- XSelectionHandler interface
+ void handleXSelectionAnnounce(bool available) override;
+ void handleXSelectionData(const char* data) override;
// -=- TXGlobalEventHandler interface
virtual bool handleGlobalEvent(XEvent* ev);
@@ -80,6 +90,7 @@ protected:
rfb::VNCServer* server;
QueryConnectDialog* queryConnectDialog;
network::Socket* queryConnectSock;
+ XSelection selection;
int oldButtonMask;
bool haveXtest;
bool haveDamage;
diff --git a/unix/x0vncserver/XSelection.cxx b/unix/x0vncserver/XSelection.cxx
new file mode 100644
index 0000000..72dd537
--- /dev/null
+++ b/unix/x0vncserver/XSelection.cxx
@@ -0,0 +1,195 @@
+/* Copyright (C) 2024 Gaurav Ujjwal. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <X11/Xatom.h>
+#include <rfb/Configuration.h>
+#include <rfb/LogWriter.h>
+#include <rfb/util.h>
+#include <x0vncserver/XSelection.h>
+
+rfb::BoolParameter setPrimary("SetPrimary",
+ "Set the PRIMARY as well as the CLIPBOARD selection",
+ true);
+rfb::BoolParameter sendPrimary("SendPrimary",
+ "Send the PRIMARY as well as the CLIPBOARD selection",
+ true);
+
+static rfb::LogWriter vlog("XSelection");
+
+XSelection::XSelection(Display* dpy_, XSelectionHandler* handler_)
+ : TXWindow(dpy_, 1, 1, nullptr), handler(handler_), announcedSelection(None)
+{
+ probeProperty = XInternAtom(dpy, "TigerVNC_ProbeProperty", False);
+ transferProperty = XInternAtom(dpy, "TigerVNC_TransferProperty", False);
+ timestampProperty = XInternAtom(dpy, "TigerVNC_TimestampProperty", False);
+ setName("TigerVNC Clipboard (x0vncserver)");
+ addEventMask(PropertyChangeMask); // Required for PropertyNotify events
+}
+
+static Bool PropertyEventMatcher(Display* /* dpy */, XEvent* ev, XPointer prop)
+{
+ if (ev->type == PropertyNotify && ev->xproperty.atom == *((Atom*)prop))
+ return True;
+ else
+ return False;
+}
+
+Time XSelection::getXServerTime()
+{
+ XEvent ev;
+ uint8_t data = 0;
+
+ // Trigger a PropertyNotify event to extract server time
+ XChangeProperty(dpy, win(), timestampProperty, XA_STRING, 8, PropModeReplace,
+ &data, sizeof(data));
+ XIfEvent(dpy, &ev, &PropertyEventMatcher, (XPointer)&timestampProperty);
+ return ev.xproperty.time;
+}
+
+// Takes ownership of selections, backed by given data.
+void XSelection::handleClientClipboardData(const char* data)
+{
+ vlog.debug("Received client clipboard data, taking selection ownership");
+
+ Time time = getXServerTime();
+ ownSelection(xaCLIPBOARD, time);
+ if (!selectionOwner(xaCLIPBOARD))
+ vlog.error("Unable to own CLIPBOARD selection");
+
+ if (setPrimary) {
+ ownSelection(XA_PRIMARY, time);
+ if (!selectionOwner(XA_PRIMARY))
+ vlog.error("Unable to own PRIMARY selection");
+ }
+
+ if (selectionOwner(xaCLIPBOARD) || selectionOwner(XA_PRIMARY))
+ clientData = data;
+}
+
+// We own the selection and another X app has asked for data
+bool XSelection::selectionRequest(Window requestor, Atom selection, Atom target,
+ Atom property)
+{
+ if (clientData.empty() || requestor == win() || !selectionOwner(selection))
+ return false;
+
+ if (target == XA_STRING) {
+ std::string latin1 = rfb::utf8ToLatin1(clientData.data(), clientData.length());
+ XChangeProperty(dpy, requestor, property, XA_STRING, 8, PropModeReplace,
+ (unsigned char*)latin1.data(), latin1.length());
+ return true;
+ }
+
+ if (target == xaUTF8_STRING) {
+ XChangeProperty(dpy, requestor, property, xaUTF8_STRING, 8, PropModeReplace,
+ (unsigned char*)clientData.data(), clientData.length());
+ return true;
+ }
+
+ return false;
+}
+
+// Selection-owner change implies a change in selection data.
+void XSelection::handleSelectionOwnerChange(Window owner, Atom selection, Time time)
+{
+ if (selection != XA_PRIMARY && selection != xaCLIPBOARD)
+ return;
+ if (selection == XA_PRIMARY && !sendPrimary)
+ return;
+
+ if (selection == announcedSelection)
+ announceSelection(None);
+
+ if (owner == None || owner == win())
+ return;
+
+ if (!selectionOwner(XA_PRIMARY) && !selectionOwner(xaCLIPBOARD))
+ clientData = "";
+
+ XConvertSelection(dpy, selection, xaTARGETS, probeProperty, win(), time);
+}
+
+void XSelection::announceSelection(Atom selection)
+{
+ announcedSelection = selection;
+ handler->handleXSelectionAnnounce(selection != None);
+}
+
+void XSelection::requestSelectionData()
+{
+ if (announcedSelection != None)
+ XConvertSelection(dpy, announcedSelection, xaTARGETS, transferProperty, win(),
+ CurrentTime);
+}
+
+// Some information about selection is received from current owner
+void XSelection::selectionNotify(XSelectionEvent* ev, Atom type, int format,
+ int nitems, void* data)
+{
+ if (!ev || !data || type == None)
+ return;
+
+ if (ev->target == xaTARGETS) {
+ if (format != 32 || type != XA_ATOM)
+ return;
+
+ Atom* targets = (Atom*)data;
+ bool utf8Supported = false;
+ bool stringSupported = false;
+
+ for (int i = 0; i < nitems; i++) {
+ if (targets[i] == xaUTF8_STRING)
+ utf8Supported = true;
+ else if (targets[i] == XA_STRING)
+ stringSupported = true;
+ }
+
+ if (ev->property == probeProperty) {
+ // Only probing for now, will issue real request when client asks for data
+ if (stringSupported || utf8Supported)
+ announceSelection(ev->selection);
+ return;
+ }
+
+ // Prefer UTF-8 if available
+ if (utf8Supported)
+ XConvertSelection(dpy, ev->selection, xaUTF8_STRING, transferProperty, win(),
+ ev->time);
+ else if (stringSupported)
+ XConvertSelection(dpy, ev->selection, XA_STRING, transferProperty, win(),
+ ev->time);
+ } else if (ev->target == xaUTF8_STRING || ev->target == XA_STRING) {
+ if (type == xaINCR) {
+ // Incremental transfer is not supported
+ vlog.debug("Selected data is too big!");
+ return;
+ }
+
+ if (format != 8)
+ return;
+
+ if (type == xaUTF8_STRING) {
+ std::string result = rfb::convertLF((char*)data, nitems);
+ handler->handleXSelectionData(result.c_str());
+ } else if (type == XA_STRING) {
+ std::string result = rfb::convertLF((char*)data, nitems);
+ result = rfb::latin1ToUTF8(result.data(), result.length());
+ handler->handleXSelectionData(result.c_str());
+ }
+ }
+}
\ No newline at end of file
diff --git a/unix/x0vncserver/XSelection.h b/unix/x0vncserver/XSelection.h
new file mode 100644
index 0000000..fbe1f29
--- /dev/null
+++ b/unix/x0vncserver/XSelection.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2024 Gaurav Ujjwal. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __XSELECTION_H__
+#define __XSELECTION_H__
+
+#include <string>
+#include <tx/TXWindow.h>
+
+class XSelectionHandler
+{
+public:
+ virtual void handleXSelectionAnnounce(bool available) = 0;
+ virtual void handleXSelectionData(const char* data) = 0;
+};
+
+class XSelection : TXWindow
+{
+public:
+ XSelection(Display* dpy_, XSelectionHandler* handler_);
+
+ void handleSelectionOwnerChange(Window owner, Atom selection, Time time);
+ void requestSelectionData();
+ void handleClientClipboardData(const char* data);
+
+private:
+ XSelectionHandler* handler;
+ Atom probeProperty;
+ Atom transferProperty;
+ Atom timestampProperty;
+ Atom announcedSelection;
+ std::string clientData; // Always in UTF-8
+
+ Time getXServerTime();
+ void announceSelection(Atom selection);
+
+ bool selectionRequest(Window requestor, Atom selection, Atom target,
+ Atom property) override;
+ void selectionNotify(XSelectionEvent* ev, Atom type, int format, int nitems,
+ void* data) override;
+};
+
+#endif
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index d2999e2..b31450b 100644
--- a/unix/x0vncserver/x0vncserver.cxx
+++ b/unix/x0vncserver/x0vncserver.cxx
@@ -281,11 +281,6 @@ int main(int argc, char** argv)
Configuration::enableServerParams();
- // FIXME: We don't support clipboard yet
- Configuration::removeParam("AcceptCutText");
- Configuration::removeParam("SendCutText");
- Configuration::removeParam("MaxCutText");
-
// Assume different defaults when socket activated
if (hasSystemdListeners())
rfbport.setParam(-1);
diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man
index 347e50e..5bc8807 100644
--- a/unix/x0vncserver/x0vncserver.man
+++ b/unix/x0vncserver/x0vncserver.man
@@ -222,6 +222,27 @@ Accept pointer movement and button events from clients. Default is on.
Accept requests to resize the size of the desktop. Default is on.
.
.TP
+.B \-AcceptCutText
+Accept clipboard updates from clients. Default is on.
+.
+.TP
+.B \-SetPrimary
+Set the PRIMARY as well as the CLIPBOARD selection. Default is on.
+.
+.TP
+.B \-MaxCutText \fIbytes\fP
+The maximum permitted size of an incoming clipboard update.
+Default is \fB262144\fP.
+.
+.TP
+.B \-SendCutText
+Send clipboard changes to clients. Default is on.
+.
+.TP
+.B \-SendPrimary
+Send the PRIMARY as well as the CLIPBOARD selection to clients. Default is on.
+.
+.TP
.B \-RemapKeys \fImapping
Sets up a keyboard mapping.
.I mapping

View File

@ -17,17 +17,17 @@ with 'PlainUsers=*' option allowing everyone to connect to the session.
5 files changed, 159 insertions(+), 7 deletions(-)
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 35a8384..80fdb86 100644
index b99d33b..aa8d53e 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -699,13 +699,6 @@ void VNCServerST::queryConnection(VNCSConnectionST* client,
@@ -682,13 +682,6 @@ void VNCServerST::queryConnection(VNCSConnectionST* client,
return;
}
- // - Are we configured to do queries?
- if (!rfb::Server::queryConnect &&
- !client->getSock()->requiresQuery()) {
- approveConnection(client->getSock(), true, NULL);
- approveConnection(client->getSock(), true, nullptr);
- return;
- }
-
@ -35,18 +35,18 @@ index 35a8384..80fdb86 100644
if (client->accessCheck(AccessNoQuery))
{
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
index 1e52987..a87373b 100644
index b43e3f7..3d00e23 100644
--- a/unix/x0vncserver/XDesktop.cxx
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -30,6 +30,7 @@
@@ -31,6 +31,7 @@
#include <network/Socket.h>
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
+#include <rfb/ServerCore.h>
#include <x0vncserver/XDesktop.h>
@@ -313,6 +314,13 @@ void XDesktop::queryConnection(network::Socket* sock,
@@ -320,6 +321,13 @@ void XDesktop::queryConnection(network::Socket* sock,
{
assert(isRunning());
@ -61,10 +61,10 @@ index 1e52987..a87373b 100644
if (queryConnectSock) {
std::list<network::Socket*> sockets;
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index d4ee16b..e12b88c 100644
index 260ed3a..c8741f6 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -52,6 +52,11 @@
@@ -51,6 +51,11 @@
#include "XorgGlue.h"
#include "vncInput.h"
@ -76,7 +76,7 @@ index d4ee16b..e12b88c 100644
extern "C" {
void vncSetGlueContext(int screenIndex);
void vncPresentMscEvent(uint64_t id, uint64_t msc);
@@ -72,6 +77,15 @@ IntParameter queryConnectTimeout("QueryConnectTimeout",
@@ -71,6 +76,15 @@ IntParameter queryConnectTimeout("QueryConnectTimeout",
"rejecting the connection",
10);
@ -92,7 +92,7 @@ index d4ee16b..e12b88c 100644
XserverDesktop::XserverDesktop(int screenIndex_,
std::list<network::SocketListener*> listeners_,
@@ -168,11 +182,134 @@ void XserverDesktop::init(rfb::VNCServer* vs)
@@ -164,11 +178,134 @@ void XserverDesktop::init(rfb::VNCServer* vs)
// ready state
}
@ -228,11 +228,11 @@ index d4ee16b..e12b88c 100644
server->approveConnection(sock, false, "Another connection is currently being queried.");
return;
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index e604295..aed188e 100644
index 8c543db..8d6bde4 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -108,6 +108,13 @@ public:
virtual void grabRegion(const rfb::Region& r);
void grabRegion(const rfb::Region& r) override;
protected:
+#ifdef HAVE_SYSTEMD_DAEMON
@ -246,11 +246,11 @@ index e604295..aed188e 100644
std::list<network::SocketListener*>* sockets,
rfb::VNCServer* sockserv);
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
index b9c429f..5762125 100644
index d6b1664..24384df 100644
--- a/unix/xserver/hw/vnc/Xvnc.man
+++ b/unix/xserver/hw/vnc/Xvnc.man
@@ -204,6 +204,13 @@ 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.
@@ -200,6 +200,13 @@ Never treat incoming connections as shared, regardless of the client-specified
setting. Default is off.
.
.TP
+.B \-ApproveLoggedUserOnly

View File

@ -0,0 +1,27 @@
From 313200978926cc7b7521c0d645918391b7609681 Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
Date: Thu, 27 Feb 2025 13:49:02 +0100
Subject: [PATCH] Add SELinux policy rules allowing to access
/proc/sys/fs/nr_open
This is needed when the nofile limit is set to unlimited, otherwise we
will fail to start a VNC session.
---
unix/vncserver/selinux/vncsession.te | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/unix/vncserver/selinux/vncsession.te b/unix/vncserver/selinux/vncsession.te
index d92f1bd..2ce4fc8 100644
--- a/unix/vncserver/selinux/vncsession.te
+++ b/unix/vncserver/selinux/vncsession.te
@@ -37,6 +37,10 @@ allow vnc_session_t self:fifo_file rw_fifo_file_perms;
allow vnc_session_t vnc_session_var_run_t:file manage_file_perms;
files_pid_filetrans(vnc_session_t, vnc_session_var_run_t, file)
+# Allow access to /proc/sys/fs/nr_open
+# Needed when the nofile limit is set to unlimited.
+kernel_read_fs_sysctls(vnc_session_t)
+
# Allowed to create ~/.local
optional_policy(`
gnome_filetrans_home_content(vnc_session_t)

View File

@ -0,0 +1,47 @@
From e652f06940f84fd8e19d7b674ae8c6000530fb40 Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
Date: Fri, 7 Feb 2025 15:32:49 +0100
Subject: [PATCH] Add SELinux policy rules allowing to create directories under
/root
We have policy that allows to create ~/.local or ~/.config, but we don't
have rule that allows the same under /root directory, where we fail in
case any of these directories doesn't exist.
---
unix/vncserver/selinux/vncsession.te | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/unix/vncserver/selinux/vncsession.te b/unix/vncserver/selinux/vncsession.te
index d92f1bda7d..2f49717077 100644
--- a/unix/vncserver/selinux/vncsession.te
+++ b/unix/vncserver/selinux/vncsession.te
@@ -48,6 +48,14 @@ optional_policy(`
create_dirs_pattern(vnc_session_t, gconf_home_t, gconf_home_t)
')
+# Allowed to create /root/.local
+optional_policy(`
+ gen_require(`
+ type admin_home_t;
+ ')
+ create_dirs_pattern(vnc_session_t, admin_home_t, admin_home_t)
+')
+
# Manage TigerVNC files (mainly ~/.local/state/*.log)
create_dirs_pattern(vnc_session_t, vnc_home_t, vnc_home_t)
manage_files_pattern(vnc_session_t, vnc_home_t, vnc_home_t)
@@ -88,6 +96,7 @@ optional_policy(`
gen_require(`
attribute userdomain;
type gconf_home_t;
+ type admin_home_t;
')
userdom_admin_home_dir_filetrans(userdomain, vnc_home_t, dir, ".vnc")
userdom_user_home_dir_filetrans(userdomain, vnc_home_t, dir, ".vnc")
@@ -95,5 +104,6 @@ optional_policy(`
gnome_config_filetrans(userdomain, vnc_home_t, dir, "tigervnc")
gnome_data_filetrans(userdomain, vnc_home_t, dir, "tigervnc")
filetrans_pattern(userdomain, gconf_home_t, vnc_home_t, dir, "tigervnc")
+ filetrans_pattern(vnc_session_t, admin_home_t, vnc_home_t, dir, "tigervnc")
filetrans_pattern(vnc_session_t, gconf_home_t, vnc_home_t, dir, "tigervnc")
')

View File

@ -0,0 +1,14 @@
diff --git a/unix/vncpasswd/vncpasswd.cxx b/unix/vncpasswd/vncpasswd.cxx
index 466aa1a2..197d60dc 100644
--- a/unix/vncpasswd/vncpasswd.cxx
+++ b/unix/vncpasswd/vncpasswd.cxx
@@ -147,8 +147,7 @@ static std::vector<uint8_t> readpassword() {
}
if (first.size() > 8) {
- fprintf(stderr,"Password should not be greater than 8 characters\nBecause only 8 valid characters are used - try again\n");
- continue;
+ fprintf(stderr,"Password should not be greater than 8 characters\nBecause only 8 valid characters are used\n");
}
#ifdef HAVE_PWQUALITY

View File

@ -1,24 +0,0 @@
From 6c8387018b130eb4ef69ea377e9154ba04f0fd50 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman@cendio.se>
Date: Tue, 22 Oct 2024 09:58:27 +0200
Subject: [PATCH] Avoid invalid XFree for XClassHint
It seems XGetClassHint() doesn't set the pointers to NULL if there is no
name, so we need to make sure it is cleared beforehand. Otherwise we can
get an invalid pointer given to XFree().
---
unix/tx/TXWindow.cxx | 1 +
1 file changed, 1 insertion(+)
diff --git a/unix/tx/TXWindow.cxx b/unix/tx/TXWindow.cxx
index b6a29d679..639c13827 100644
--- a/unix/tx/TXWindow.cxx
+++ b/unix/tx/TXWindow.cxx
@@ -313,6 +313,7 @@ void TXWindow::toplevel(const char* name, TXDeleteWindowCallback* dwc_,
void TXWindow::setName(const char* name)
{
XClassHint classHint;
+ memset(&classHint, 0, sizeof(classHint));
XGetClassHint(dpy, win(), &classHint);
XFree(classHint.res_name);
classHint.res_name = (char*)name;

View File

@ -1,22 +0,0 @@
From 9e15952d02e01b8e19e7459bcabcd47dc63a1726 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman@cendio.se>
Date: Tue, 22 Oct 2024 09:59:30 +0200
Subject: [PATCH] Do proper top level window setup for selection window
---
unix/x0vncserver/XSelection.cxx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unix/x0vncserver/XSelection.cxx b/unix/x0vncserver/XSelection.cxx
index 72dd537f4..c724d2ac4 100644
--- a/unix/x0vncserver/XSelection.cxx
+++ b/unix/x0vncserver/XSelection.cxx
@@ -37,7 +37,7 @@ XSelection::XSelection(Display* dpy_, XSelectionHandler* handler_)
probeProperty = XInternAtom(dpy, "TigerVNC_ProbeProperty", False);
transferProperty = XInternAtom(dpy, "TigerVNC_TransferProperty", False);
timestampProperty = XInternAtom(dpy, "TigerVNC_TimestampProperty", False);
- setName("TigerVNC Clipboard (x0vncserver)");
+ toplevel("TigerVNC Clipboard (x0vncserver)");
addEventMask(PropertyChangeMask); // Required for PropertyNotify events
}

View File

@ -1,13 +0,0 @@
diff --git a/unix/xserver/hw/vnc/vncInput.c b/unix/xserver/hw/vnc/vncInput.c
index b3d0926d..d36a096f 100644
--- a/unix/xserver/hw/vnc/vncInput.c
+++ b/unix/xserver/hw/vnc/vncInput.c
@@ -167,7 +167,7 @@ void vncPointerMove(int x, int y)
void vncGetPointerPos(int *x, int *y)
{
- if (vncPointerDev != NULL) {
+ if (vncPointerDev != NULL && !IsFloating(vncPointerDev)) {
ScreenPtr ptrScreen;
miPointerGetPosition(vncPointerDev, &cursorPosX, &cursorPosY);

View File

@ -0,0 +1,47 @@
From 1f1aaca09a1f9919f5169caea9c396b14c2af765 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman@cendio.se>
Date: Tue, 8 Apr 2025 14:41:04 +0200
Subject: [PATCH] Don't print Xvnc banner before parsing args
If we'll be running in inetd mode, then stdout and stderr will be a
client socket and not an appropriate place for logging.
Mimic what Xorg does instead.
---
unix/xserver/hw/vnc/xvnc.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c
index ddb249937..a13168c47 100644
--- a/unix/xserver/hw/vnc/xvnc.c
+++ b/unix/xserver/hw/vnc/xvnc.c
@@ -446,7 +446,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
}
if (!strcmp(argv[i], "-showconfig") || !strcmp(argv[i], "-version")) {
- /* Already shown at start */
+ vncPrintBanner();
exit(0);
}
@@ -1171,8 +1171,11 @@ InitOutput(ScreenInfo * scrInfo, int argc, char **argv)
int i;
int NumFormats = 0;
- if (serverGeneration == 1)
+ if (serverGeneration == 1) {
+ vncPrintBanner();
+
LoadExtensionList(vncExtensions, ARRAY_SIZE(vncExtensions), TRUE);
+ }
#if XORG_AT_LEAST(1, 20, 0)
xorgGlxCreateVendor();
@@ -1266,7 +1269,5 @@ vncClientGone(int fd)
int
main(int argc, char *argv[], char *envp[])
{
- vncPrintBanner();
-
return dix_main(argc, argv, envp);
}

View File

@ -1,94 +0,0 @@
From e26bc65b92d1e43570619deadf20b965e0952fef Mon Sep 17 00:00:00 2001
From: Pat Riehecky <riehecky@fnal.gov>
Date: Wed, 31 Jul 2024 14:43:46 -0500
Subject: [PATCH] vncsession: Move existing log to log.old if present
---
unix/vncserver/vncsession.c | 47 ++++++++++++++++++++++++++++---------
1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/unix/vncserver/vncsession.c b/unix/vncserver/vncsession.c
index 98a0432aa..a10e0789e 100644
--- a/unix/vncserver/vncsession.c
+++ b/unix/vncserver/vncsession.c
@@ -393,8 +393,9 @@ redir_stdio(const char *homedir, const char *display, char **envp)
int fd;
long hostlen;
char* hostname = NULL, *xdgstate;
- char logfile[PATH_MAX], legacy[PATH_MAX];
+ char logdir[PATH_MAX], logfile[PATH_MAX], logfile_old[PATH_MAX], legacy[PATH_MAX];
struct stat st;
+ size_t fmt_len;
fd = open("/dev/null", O_RDONLY);
if (fd == -1) {
@@ -408,15 +409,24 @@ redir_stdio(const char *homedir, const char *display, char **envp)
close(fd);
xdgstate = getenvp("XDG_STATE_HOME", envp);
- if (xdgstate != NULL && xdgstate[0] == '/')
- snprintf(logfile, sizeof(logfile), "%s/tigervnc", xdgstate);
- else
- snprintf(logfile, sizeof(logfile), "%s/.local/state/tigervnc", homedir);
+ if (xdgstate != NULL && xdgstate[0] == '/') {
+ fmt_len = snprintf(logdir, sizeof(logdir), "%s/tigervnc", xdgstate);
+ if (fmt_len >= sizeof(logdir)) {
+ syslog(LOG_CRIT, "Log dir path too long");
+ _exit(EX_OSERR);
+ }
+ } else {
+ fmt_len = snprintf(logdir, sizeof(logdir), "%s/.local/state/tigervnc", homedir);
+ if (fmt_len >= sizeof(logdir)) {
+ syslog(LOG_CRIT, "Log dir path too long");
+ _exit(EX_OSERR);
+ }
+ }
snprintf(legacy, sizeof(legacy), "%s/.vnc", homedir);
- if (stat(logfile, &st) != 0 && stat(legacy, &st) == 0) {
+ if (stat(logdir, &st) != 0 && stat(legacy, &st) == 0) {
syslog(LOG_WARNING, "~/.vnc is deprecated, please consult 'man vncsession' for paths to migrate to.");
- strcpy(logfile, legacy);
+ strcpy(logdir, legacy);
#ifdef HAVE_SELINUX
/* this is only needed to handle historical type changes for the legacy dir */
@@ -431,9 +441,9 @@ redir_stdio(const char *homedir, const char *display, char **envp)
#endif
}
- if (mkdir_p(logfile, 0755) == -1) {
+ if (mkdir_p(logdir, 0755) == -1) {
if (errno != EEXIST) {
- syslog(LOG_CRIT, "Failure creating \"%s\": %s", logfile, strerror(errno));
+ syslog(LOG_CRIT, "Failure creating \"%s\": %s", logdir, strerror(errno));
_exit(EX_OSERR);
}
}
@@ -450,9 +460,24 @@ redir_stdio(const char *homedir, const char *display, char **envp)
_exit(EX_OSERR);
}
- snprintf(logfile + strlen(logfile), sizeof(logfile) - strlen(logfile), "/%s%s.log",
- hostname, display);
+ fmt_len = snprintf(logfile, sizeof(logfile), "/%s/%s%s.log", logdir, hostname, display);
+ if (fmt_len >= sizeof(logfile)) {
+ syslog(LOG_CRIT, "Log path too long");
+ _exit(EX_OSERR);
+ }
+ fmt_len = snprintf(logfile_old, sizeof(logfile_old), "/%s/%s%s.log.old", logdir, hostname, display);
+ if (fmt_len >= sizeof(logfile)) {
+ syslog(LOG_CRIT, "Log.old path too long");
+ _exit(EX_OSERR);
+ }
free(hostname);
+
+ if (stat(logfile, &st) == 0) {
+ if (rename(logfile, logfile_old) != 0) {
+ syslog(LOG_CRIT, "Failure renaming log file \"%s\" to \"%s\": %s", logfile, logfile_old, strerror(errno));
+ _exit(EX_OSERR);
+ }
+ }
fd = open(logfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
syslog(LOG_CRIT, "Failure creating log file \"%s\": %s", logfile, strerror(errno));

View File

@ -1,138 +0,0 @@
diff --git a/configure.ac b/configure.ac
index 0909cc5b4..c01873200 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
AC_CONFIG_HEADERS(include/version-config.h)
AM_PROG_AS
+AC_PROG_CXX
AC_PROG_LN_S
LT_PREREQ([2.2])
LT_INIT([disable-static win32-dll])
@@ -1735,6 +1736,14 @@ if test "x$XVFB" = xyes; then
AC_SUBST([XVFB_SYS_LIBS])
fi
+dnl Xvnc DDX
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
+
+PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
+if test "x$GBM" = xyes; then
+ AC_DEFINE(HAVE_GBM, 1, [Have GBM support])
+fi
dnl Xnest DDX
@@ -2058,7 +2067,6 @@ if test "x$GLAMOR" = xyes; then
[AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DRIVER, 1, [Have GLAMOR_HAS_EGL_QUERY_DRIVER])],
[])
- PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
if test "x$GBM" = xyes; then
AC_DEFINE(GLAMOR_HAS_GBM, 1,
[Build glamor with GBM-based EGL support])
@@ -2523,6 +2531,7 @@ hw/dmx/Makefile
hw/dmx/man/Makefile
hw/vfb/Makefile
hw/vfb/man/Makefile
+hw/vnc/Makefile
hw/xnest/Makefile
hw/xnest/man/Makefile
hw/xwin/Makefile
diff --git a/dri3/Makefile.am b/dri3/Makefile.am
index e47a734e0..99c3718a5 100644
--- a/dri3/Makefile.am
+++ b/dri3/Makefile.am
@@ -1,7 +1,7 @@
noinst_LTLIBRARIES = libdri3.la
AM_CFLAGS = \
- -DHAVE_XORG_CONFIG_H \
- @DIX_CFLAGS@ @XORG_CFLAGS@
+ @DIX_CFLAGS@ \
+ @LIBDRM_CFLAGS@
libdri3_la_SOURCES = \
dri3.h \
diff --git a/dri3/dri3.c b/dri3/dri3.c
index ba32facd7..191252969 100644
--- a/dri3/dri3.c
+++ b/dri3/dri3.c
@@ -20,10 +20,6 @@
* OF THIS SOFTWARE.
*/
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
#include "dri3_priv.h"
#include <drm_fourcc.h>
diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
index b087a9529..f319d1770 100644
--- a/dri3/dri3_priv.h
+++ b/dri3/dri3_priv.h
@@ -23,6 +23,7 @@
#ifndef _DRI3PRIV_H_
#define _DRI3PRIV_H_
+#include "dix-config.h"
#include <X11/X.h>
#include "scrnintstr.h"
#include "misc.h"
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
index 958877efa..687168930 100644
--- a/dri3/dri3_request.c
+++ b/dri3/dri3_request.c
@@ -20,10 +20,6 @@
* OF THIS SOFTWARE.
*/
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
#include "dri3_priv.h"
#include <syncsrv.h>
#include <unistd.h>
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
index b98259753..3c7e5bf60 100644
--- a/dri3/dri3_screen.c
+++ b/dri3/dri3_screen.c
@@ -20,10 +20,6 @@
* OF THIS SOFTWARE.
*/
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
#include "dri3_priv.h"
#include <syncsdk.h>
#include <misync.h>
diff --git a/hw/Makefile.am b/hw/Makefile.am
index 19895dc77..3ecfa8b7a 100644
--- a/hw/Makefile.am
+++ b/hw/Makefile.am
@@ -44,3 +44,5 @@ DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
relink:
$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
+
+SUBDIRS += vnc
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index f8fc67067..d53c4e72f 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -83,6 +83,9 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
+/* Have GBM support */
+#undef HAVE_GBM
+
/* Define to 1 if you have the `getdtablesize' function. */
#undef HAVE_GETDTABLESIZE

View File

@ -1,87 +0,0 @@
From 53e0de91e307870b6790690bd74cf30ac501de50 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 28 Mar 2025 09:43:52 +0100
Subject: [PATCH xserver] render: Avoid 0 or less animated cursors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Animated cursors use a series of cursors that the client can set.
By default, the Xserver assumes at least one cursor is specified
while a client may actually pass no cursor at all.
That causes an out-of-bound read creating the animated cursor and a
crash of the Xserver:
| Invalid read of size 8
| at 0x5323F4: AnimCursorCreate (animcur.c:325)
| by 0x52D4C5: ProcRenderCreateAnimCursor (render.c:1817)
| by 0x52DC80: ProcRenderDispatch (render.c:1999)
| by 0x4A1E9D: Dispatch (dispatch.c:560)
| by 0x4B0169: dix_main (main.c:284)
| by 0x4287F5: main (stubmain.c:34)
| Address 0x59aa010 is 0 bytes after a block of size 0 alloc'd
| at 0x48468D3: reallocarray (vg_replace_malloc.c:1803)
| by 0x52D3DA: ProcRenderCreateAnimCursor (render.c:1802)
| by 0x52DC80: ProcRenderDispatch (render.c:1999)
| by 0x4A1E9D: Dispatch (dispatch.c:560)
| by 0x4B0169: dix_main (main.c:284)
| by 0x4287F5: main (stubmain.c:34)
|
| Invalid read of size 2
| at 0x5323F7: AnimCursorCreate (animcur.c:325)
| by 0x52D4C5: ProcRenderCreateAnimCursor (render.c:1817)
| by 0x52DC80: ProcRenderDispatch (render.c:1999)
| by 0x4A1E9D: Dispatch (dispatch.c:560)
| by 0x4B0169: dix_main (main.c:284)
| by 0x4287F5: main (stubmain.c:34)
| Address 0x8 is not stack'd, malloc'd or (recently) free'd
To avoid the issue, check the number of cursors specified and return a
BadValue error in both the proc handler (early) and the animated cursor
creation (as this is a public function) if there is 0 or less cursor.
CVE-2025-49175
This issue was discovered by Nils Emmerich <nemmerich@ernw.de> and
reported by Julian Suleder via ERNW Vulnerability Disclosure.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: José Expósito <jexposit@redhat.com>
(cherry picked from commit 9304e31035f97ddbfcc1d5f3c178da1d04a472ad)
---
render/animcur.c | 3 +++
render/render.c | 2 ++
2 files changed, 5 insertions(+)
diff --git a/render/animcur.c b/render/animcur.c
index ef27bda27..77942d846 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -304,6 +304,9 @@ AnimCursorCreate(CursorPtr *cursors, CARD32 *deltas, int ncursor,
int rc = BadAlloc, i;
AnimCurPtr ac;
+ if (ncursor <= 0)
+ return BadValue;
+
for (i = 0; i < screenInfo.numScreens; i++)
if (!GetAnimCurScreen(screenInfo.screens[i]))
return BadImplementation;
diff --git a/render/render.c b/render/render.c
index 5bc2a204b..a8c2da056 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1795,6 +1795,8 @@ ProcRenderCreateAnimCursor(ClientPtr client)
ncursor =
(client->req_len -
(bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1;
+ if (ncursor <= 0)
+ return BadValue;
cursors = xallocarray(ncursor, sizeof(CursorPtr) + sizeof(CARD32));
if (!cursors)
return BadAlloc;
--
2.49.0

View File

@ -1,88 +0,0 @@
From 57248c57e971bb7cc0ccae6de4c49a49ff13b45c Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 7 Apr 2025 16:13:34 +0200
Subject: [PATCH xserver] os: Do not overflow the integer size with BigRequest
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The BigRequest extension allows request larger than the 16-bit length
limit.
It uses integers for the request length and checks for the size not to
exceed the maxBigRequestSize limit, but does so after translating the
length to integer by multiplying the given size in bytes by 4.
In doing so, it might overflow the integer size limit before actually
checking for the overflow, defeating the purpose of the test.
To avoid the issue, make sure to check that the request size does not
overflow the maxBigRequestSize limit prior to any conversion.
The caller Dispatch() function however expects the return value to be in
bytes, so we cannot just return the converted value in case of error, as
that would also overflow the integer size.
To preserve the existing API, we use a negative value for the X11 error
code BadLength as the function only return positive values, 0 or -1 and
update the caller Dispatch() function to take that case into account to
return the error code to the offending client.
CVE-2025-49176
This issue was discovered by Nils Emmerich <nemmerich@ernw.de> and
reported by Julian Suleder via ERNW Vulnerability Disclosure.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
(cherry picked from commit b380b0a6c2022fbd3115552b1cd88251b5268daa)
---
dix/dispatch.c | 9 +++++----
os/io.c | 4 ++++
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 6f4e349e0..15e63e22a 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -518,9 +518,10 @@ Dispatch(void)
/* now, finally, deal with client requests */
result = ReadRequestFromClient(client);
- if (result <= 0) {
- if (result < 0)
- CloseDownClient(client);
+ if (result == 0)
+ break;
+ else if (result == -1) {
+ CloseDownClient(client);
break;
}
@@ -541,7 +542,7 @@ Dispatch(void)
client->index,
client->requestBuffer);
#endif
- if (result > (maxBigRequestSize << 2))
+ if (result < 0 || result > (maxBigRequestSize << 2))
result = BadLength;
else {
result = XaceHookDispatch(client, client->majorOp);
diff --git a/os/io.c b/os/io.c
index 5b7fac349..5fc05821c 100644
--- a/os/io.c
+++ b/os/io.c
@@ -296,6 +296,10 @@ ReadRequestFromClient(ClientPtr client)
needed = get_big_req_len(request, client);
}
client->req_len = needed;
+ if (needed > MAXINT >> 2) {
+ /* Check for potential integer overflow */
+ return -(BadLength);
+ }
needed <<= 2; /* needed is in bytes now */
}
if (gotnow < needed) {
--
2.49.0

View File

@ -1,32 +0,0 @@
From 6794bf46b1c76c0a424940c97be3576dc2e7e9b1 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Wed, 18 Jun 2025 08:39:02 +0200
Subject: [PATCH] os: Check for integer overflow on BigRequest length
Check for another possible integer overflow once we get a complete xReq
with BigRequest.
Related to CVE-2025-49176
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Suggested-by: Peter Harris <pharris2@rocketsoftware.com>
---
os/io.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/os/io.c b/os/io.c
index e7b76b9cea..167b40a720 100644
--- a/os/io.c
+++ b/os/io.c
@@ -394,6 +394,8 @@ ReadRequestFromClient(ClientPtr client)
needed = get_big_req_len(request, client);
}
client->req_len = needed;
+ if (needed > MAXINT >> 2)
+ return -(BadLength);
needed <<= 2;
}
if (gotnow < needed) {
--
GitLab

View File

@ -1,46 +0,0 @@
From 90a13c564e7b9ba5c0d8d92acac80689cd051898 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 28 Apr 2025 10:46:03 +0200
Subject: [PATCH xserver] os: Account for bytes to ignore when sharing input
buffer
When reading requests from the clients, the input buffer might be shared
and used between different clients.
If a given client sends a full request with non-zero bytes to ignore,
the bytes to ignore may still be non-zero even though the request is
full, in which case the buffer could be shared with another client who's
request will not be processed because of those bytes to ignore, leading
to a possible hang of the other client request.
To avoid the issue, make sure we have zero bytes to ignore left in the
input request when sharing the input buffer with another client.
CVE-2025-49178
This issue was discovered by Nils Emmerich <nemmerich@ernw.de> and
reported by Julian Suleder via ERNW Vulnerability Disclosure.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit b0c1cbf4f8e6baa372b1676d2f30512de8ab4ed3)
---
os/io.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/os/io.c b/os/io.c
index 5fc05821c..26f9161ef 100644
--- a/os/io.c
+++ b/os/io.c
@@ -442,7 +442,7 @@ ReadRequestFromClient(ClientPtr client)
*/
gotnow -= needed;
- if (!gotnow)
+ if (!gotnow && !oci->ignoreBytes)
AvailableInput = oc;
if (move_header) {
if (client->req_len < bytes_to_int32(sizeof(xBigReq) - sizeof(xReq))) {
--
2.49.0

View File

@ -1,62 +0,0 @@
From 9a4f3012ba5752be1634455a3f0c7c125eabb328 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 28 Apr 2025 11:47:15 +0200
Subject: [PATCH xserver] record: Check for overflow in
RecordSanityCheckRegisterClients()
The RecordSanityCheckRegisterClients() checks for the request length,
but does not check for integer overflow.
A client might send a very large value for either the number of clients
or the number of protocol ranges that will cause an integer overflow in
the request length computation, defeating the check for request length.
To avoid the issue, explicitly check the number of clients against the
limit of clients (which is much lower than an maximum integer value) and
the number of protocol ranges (multiplied by the record length) do not
exceed the maximum integer value.
This way, we ensure that the final computation for the request length
will not overflow the maximum integer limit.
CVE-2025-49179
This issue was discovered by Nils Emmerich <nemmerich@ernw.de> and
reported by Julian Suleder via ERNW Vulnerability Disclosure.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit ea52403bf222f8bd6ee4c509bed5e34f0c789b00)
---
record/record.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/record/record.c b/record/record.c
index e123867a7..018e53f81 100644
--- a/record/record.c
+++ b/record/record.c
@@ -45,6 +45,7 @@ and Jim Haggerty of Metheus.
#include "inputstr.h"
#include "eventconvert.h"
#include "scrnintstr.h"
+#include "opaque.h"
#include <stdio.h>
#include <assert.h>
@@ -1298,6 +1299,13 @@ RecordSanityCheckRegisterClients(RecordContextPtr pContext, ClientPtr client,
int i;
XID recordingClient;
+ /* LimitClients is 2048 at max, way less that MAXINT */
+ if (stuff->nClients > LimitClients)
+ return BadValue;
+
+ if (stuff->nRanges > (MAXINT - 4 * stuff->nClients) / SIZEOF(xRecordRange))
+ return BadValue;
+
if (((client->req_len << 2) - SIZEOF(xRecordRegisterClientsReq)) !=
4 * stuff->nClients + SIZEOF(xRecordRange) * stuff->nRanges)
return BadLength;
--
2.49.0

View File

@ -1,41 +0,0 @@
From 5e7a3a955853218536ba4a7e696360aab0064206 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Tue, 20 May 2025 15:18:19 +0200
Subject: [PATCH xserver 1/2] randr: Check for overflow in
RRChangeProviderProperty()
A client might send a request causing an integer overflow when computing
the total size to allocate in RRChangeProviderProperty().
To avoid the issue, check that total length in bytes won't exceed the
maximum integer value.
CVE-2025-49180
This issue was discovered by Nils Emmerich <nemmerich@ernw.de> and
reported by Julian Suleder via ERNW Vulnerability Disclosure.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 1b0bf563a3a76b06ddcd6fc4d8e72d81f6773699)
---
randr/rrproviderproperty.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/randr/rrproviderproperty.c b/randr/rrproviderproperty.c
index 90c5a9a93..0aa35ad87 100644
--- a/randr/rrproviderproperty.c
+++ b/randr/rrproviderproperty.c
@@ -179,7 +179,8 @@ RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type,
if (mode == PropModeReplace || len > 0) {
void *new_data = NULL, *old_data = NULL;
-
+ if (total_len > MAXINT / size_in_bytes)
+ return BadValue;
total_size = total_len * size_in_bytes;
new_value.data = (void *) malloc(total_size);
if (!new_value.data && total_size) {
--
2.49.0

View File

@ -4,8 +4,8 @@
%global modulename vncsession
Name: tigervnc
Version: 1.14.1
Release: 9%{?dist}
Version: 1.15.0
Release: 6%{?dist}
Summary: A TigerVNC remote display system
%global _hardened_build 1
@ -13,7 +13,7 @@ Summary: A TigerVNC remote display system
License: GPL-2.0-or-later
URL: http://www.tigervnc.com
Source0: %{name}-%{version}.tar.gz
Source0: https://github.com/TigerVNC/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
Source1: xvnc.service
Source2: xvnc.socket
Source3: 10-libvnc.conf
@ -27,35 +27,28 @@ Patch1: tigervnc-use-gnome-as-default-session.patch
Patch2: tigervnc-vncsession-restore-script-systemd-service.patch
# https://github.com/TigerVNC/tigervnc/pull/1792
Patch3: tigervnc-add-option-allowing-to-connect-only-user-owning-session.patch
# Only warn about passwords longer than 8 characters, but allow them to be used as in the past
Patch4: tigervnc-allow-use-of-passwords-longer-than-eight-characters.patch
# Upstream patches
Patch50: tigervnc-vncsession-move-existing-log-to-log-old-if-present.patch
Patch51: tigervnc-add-clipboard-support-to-x0vncserver.patch
Patch52: tigervnc-do-proper-toplevel-window-setup-for-selection-window.patch
Patch53: tigervnc-avoid-invalid-xfree-for-xclasshint.patch
Patch50: tigervnc-add-selinux-policy-rules-allowing-create-dirs-under-root-dir.patch
Patch51: tigervnc-add-selinux-policy-rules-allowing-access-to-proc-sys-fs-nr-open.patch
Patch52: tigervnc-dont-print-xvnc-banner-before-parsing-args.patch
# Upstreamable patches
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
Patch100: 0001-rpath-hack.patch
# XServer patches
Patch200: xorg-CVE-2025-49175.patch
Patch201: xorg-CVE-2025-49176-1.patch
Patch202: xorg-CVE-2025-49176-2.patch
Patch203: xorg-CVE-2025-49178.patch
Patch204: xorg-CVE-2025-49179.patch
Patch205: xorg-CVE-2025-49180.patch
# CVE-2025-62229: Use-after-free in XPresentNotify structures creation
Patch206: xorg-CVE-2025-62229.patch
Patch200: xorg-CVE-2025-62229.patch
# CVE-2025-62230: Use-after-free in Xkb client resource removal
Patch207: xorg-CVE-2025-62230-1.patch
Patch208: xorg-CVE-2025-62230-2.patch
Patch201: xorg-CVE-2025-62230-1.patch
Patch202: xorg-CVE-2025-62230-2.patch
# CVE-2025-62231: Value overflow in Xkb extension XkbSetCompatMap()
Patch209: xorg-CVE-2025-62231.patch
Patch203: xorg-CVE-2025-62231.patch
BuildRequires: make
BuildRequires: gcc-c++
@ -119,6 +112,7 @@ Requires(postun):coreutils
Requires: hicolor-icon-theme
Requires: tigervnc-license
Requires: tigervnc-icons
Requires: which
%description
Virtual Network Computing (VNC) is a remote display system which
@ -154,8 +148,11 @@ Requires(preun): systemd
Requires(postun): systemd
Requires(post): systemd
Requires: mesa-dri-drivers, xkeyboard-config, xkbcomp
Requires: tigervnc-license, dbus-x11
Requires: dbus-x11
Requires: mesa-dri-drivers
Requires: tigervnc-license
Requires: xkbcomp
Requires: xkeyboard-config
%description server-minimal
The VNC system allows you to access the same desktop from a wide
@ -211,35 +208,27 @@ pushd unix/xserver
for all in `find . -type f -perm -001`; do
chmod -x "$all"
done
# Xorg patches
%patch -P100 -p1 -b .xserver120-rebased
%patch -P101 -p1 -b .rpath
# Xorg CVEs
%patch -P200 -p1 -b .xorg-CVE-2025-49175
%patch -P201 -p1 -b .xorg-CVE-2025-49176-1
%patch -P202 -p1 -b .xorg-CVE-2025-49176-2
%patch -P203 -p1 -b .xorg-CVE-2025-49178
%patch -P204 -p1 -b .xorg-CVE-2025-49179
%patch -P205 -p1 -b .xorg-CVE-2025-49180
%patch -P206 -p1 -b .xorg-CVE-2025-62229
%patch -P207 -p1 -b .xorg-CVE-2025-62230-1
%patch -P208 -p1 -b .xorg-CVE-2025-62230-2
%patch -P209 -p1 -b .xorg-CVE-2025-62231
%patch -P100 -p1 -b .rpath
cat ../xserver120.patch | patch -p1
%patch -P200 -p1 -b .xorg-CVE-2025-62229
%patch -P201 -p1 -b .xorg-CVE-2025-62230-1
%patch -P202 -p1 -b .xorg-CVE-2025-62230-2
%patch -P203 -p1 -b .xorg-CVE-2025-62231
popd
# Tigervnc patches
%patch -P1 -p1 -b .use-gnome-as-default-session
%patch -P2 -p1 -b .vncsession-restore-script-systemd-service
%patch -P3 -p1 -b .add-option-allowing-to-connect-only-user-owning-session
%patch -P4 -p1 -b .allow-use-of-passwords-longer-than-eight-characters
# Upstream patches
%patch -P50 -p1 -b .vncsession-move-existing-log-to-log-old-if-present
%patch -P51 -p1 -b .add-clipboard-support-to-x0vncserver
%patch -P52 -p1 -b .do-proper-toplevel-window-setup-for-selection-window
%patch -P53 -p1 -b .avoid-invalid-xfree-for-xclasshint
%patch -P50 -p1 -b .add-selinux-policy-rules-allowing-create-dirs-under-root-dir
%patch -P51 -p1 -b .add-selinux-policy-rules-allowing-access-to-proc-sys-fs-nr-open
%patch -P52 -p1 -b .dont-print-xvnc-banner-before-parsing-args
# Upstreamable patches
%patch -P80 -p1 -b .dont-get-pointer-position-for-floating-device
%build
%ifarch sparcv9 sparc64 s390 s390x
@ -260,7 +249,7 @@ mkdir -p %{%__cmake_builddir}
pushd unix/xserver
%if 0%{?fedora} > 32 || 0%{?rhel} >= 9
sed -i 's@TIGERVNC_BUILDDIR=${TIGERVNC_SRCDIR}@TIGERVNC_BUILDDIR=${TIGERVNC_SRCDIR}/%{_target_platform}@g' hw/vnc/Makefile.am
sed -i 's@TIGERVNC_BUILDDIR=${top_builddir}/\.\./\.\.@TIGERVNC_BUILDDIR=${TIGERVNC_SRCDIR}/%{_target_platform}@g' hw/vnc/Makefile.am
%endif
autoreconf -fiv
@ -268,10 +257,8 @@ autoreconf -fiv
--disable-xorg --disable-xnest --disable-xvfb --disable-dmx \
--disable-xwin --disable-xephyr --disable-kdrive --disable-xwayland \
--with-pic --disable-static \
--with-default-font-path="catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins" \
--with-fontdir=%{_datadir}/X11/fonts \
--with-default-font-path="catalogue:/etc/X11/fontpath.d,built-ins" \
--with-xkb-output=%{_localstatedir}/lib/xkb \
--enable-install-libxf86config \
--enable-glx --disable-dri --enable-dri2 --enable-dri3 \
--disable-unit-tests \
--disable-config-hal \
@ -423,53 +410,67 @@ fi
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
%changelog
* Fri Oct 31 2025 Jan Grulich <jgrulich@redhat.com> - 1.14.1-9
* Fri Oct 31 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-6
- Fix CVE-2025-62229: xorg-x11-server: Use-after-free in XPresentNotify structures creation
Resolves: RHEL-119987
Resolves: RHEL-119986
- Fix CVE-2025-62230: xorg-x11-server: Use-after-free in Xkb client resource removal
Resolves: RHEL-120006
Resolves: RHEL-120007
- Fix CVE-2025-62231: xorg-x11-server: Value overflow in Xkb extension XkbSetCompatMap()
Resolves: RHEL-120769
Resolves: RHEL-120768
* Wed Jun 18 2025 Jan Grulich <jgrulich@redhat.com> - 1.14.1-8
- Additional fix to CVE-2025-49176: xorg-x11-server: Integer Overflow in Big Requests Extension
Resolves: RHEL-97305
* Tue Jun 17 2025 Jan Grulich <jgrulich@redhat.com> - 1.14.1-7
* Mon Jun 23 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-5
- Fix CVE-2025-49175: xorg-x11-server: Out-of-Bounds Read in X Rendering Extension Animated Cursors
Resolves: RHEL-97287
Resolves: RHEL-97284
- Fix CVE-2025-49176: xorg-x11-server: Integer Overflow in Big Requests Extension
Resolves: RHEL-97305
Resolves: RHEL-97303
- Fix CVE-2025-49178: xorg-x11-server: Unprocessed Client Request Due to Bytes to Ignore
Resolves: RHEL-97380
Resolves: RHEL-97379
- Fix CVE-2025-49179: xorg-x11-server: Integer overflow in X Record extension
Resolves: RHEL-97415
Resolves: RHEL-97414
- Fix CVE-2025-49180: xorg-x11-server: Integer Overflow in X Resize, Rotate and Reflect (RandR) Extension
Resolves: RHEL-97430
Resolves: RHEL-97429
* Wed May 28 2025 Jan Grulich <jgrulich@redhat.com> - 1.14.1-6
* Tue May 27 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-4
- Fix broken authentication with x0vncserver
Resolves: RHEL-93726
Resolves: RHEL-93573
* Wed Feb 26 2025 Jan Grulich <jgrulich@redhat.com> - 1.14.1-5
* Wed Apr 30 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-3
- Only warn about 8 characters limit, but let it proceed
Resolves: RHEL-89432
* Wed Apr 16 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-2
- Fix inetd mode not working
Resolves: RHEL-86511
* Fri Mar 07 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-1
- 1.15.0
Resolves: RHEL-78617
- Add SELinux policy rules allowing to access /proc/sys/fs/nr_open
Resolves: RHEL-77973
- Add SELinux policy rules allowing to create directories under /root
Resolves: RHEL-77975
- Fix CVE-2025-26594 xorg-x11-server Use-after-free of the root cursor
Resolves: RHEL-80015
Resolves: RHEL-80208
- Fix CVE-2025-26595 xorg-x11-server Buffer overflow in XkbVModMaskText()
Resolves: RHEL-80027
Resolves: RHEL-80189
- Fix CVE-2025-26596 xorg-x11-server Heap overflow in XkbWriteKeySyms()
Resolves: RHEL-79395
Resolves: RHEL-80194
- Fix CVE-2025-26597 xorg-x11-server Buffer overflow in XkbChangeTypesOfKey()
Resolves: RHEL-80035
Resolves: RHEL-80196
- Fix CVE-2025-26598 xorg-x11-server Out-of-bounds write in CreatePointerBarrierClient()
Resolves: RHEL-79378
Resolves: RHEL-80197
- Fix CVE-2025-26599 xorg-x11-server Use of uninitialized pointer in compRedirectWindow()
Resolves: RHEL-80047
Resolves: RHEL-80206
- Fix CVE-2025-26600 xorg-x11-server Use-after-free in PlayReleasedEvents()
Resolves: RHEL-80041
Resolves: RHEL-80205
- Fix CVE-2025-26601 xorg-x11-server Use-after-free in SyncInitTrigger()
Resolves: RHEL-79358
Resolves: RHEL-80209
* Tue Jan 21 2025 Jan Grulich <jgrulich@redhat.com> - 1.14.1-4
- Fix crash in clipboard support in x0vncserver