File 0001-Use-Xauthority-for-Xwayland.patch of Package kwin5
From 10011387cd146f6b92f337b4c10ac4000c981891 Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fabian@ritter-vogt.de>
Date: Sat, 17 Mar 2018 23:25:56 +0100
Subject: [PATCH] Use Xauthority for Xwayland
References: boo#1084737
Needed by kdesu, su, ...
If creation fails, it will fall back to not using it.
---
CMakeLists.txt | 1 +
main_wayland.cpp | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
main_wayland.h | 2 ++
3 files changed, 102 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbf9529ca..ba9ac6584 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -579,6 +579,7 @@ set(kwin_XLIB_LIBS
${X11_X11_LIB}
${X11_ICE_LIB}
${X11_SM_LIB}
+ ${X11_Xau_LIB}
)
set(kwin_XCB_LIBS
diff --git a/main_wayland.cpp b/main_wayland.cpp
index 2107bc85a..b3e5c6cf3 100644
--- a/main_wayland.cpp
+++ b/main_wayland.cpp
@@ -70,6 +70,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <sys/capability.h>
#endif
+#include <X11/Xauth.h>
+
#include <sched.h>
#include <iostream>
@@ -157,6 +159,16 @@ void ApplicationWayland::performStartup()
{
if (m_startXWayland) {
setOperationMode(OperationModeXwayland);
+
+ QString dir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+ if (!dir.isEmpty()) {
+ m_xwaylandAuthority.setFileTemplate(dir + QStringLiteral("/xauth_XXXXXX"));
+ m_xwaylandAuthority.open();
+ }
+
+ if (m_xwaylandAuthority.fileName().isEmpty()) {
+ std::cerr << "Warning: Could not create a Xauthority file for Xwayland." << std::endl;
+ }
}
// first load options - done internally by a different thread
createOptions();
@@ -206,8 +218,89 @@ void ApplicationWayland::continueStartupWithSceen()
notifyKSplash();
}
+static QByteArray getRandomData(qint64 bytes)
+{
+ QFile random(QStringLiteral("/dev/urandom"));
+ if (!random.open(QIODevice::ReadOnly))
+ return {};
+
+ QByteArray data;
+ data.resize(bytes);
+ while (bytes) {
+ auto bytesRead = random.read(data.data() + data.size() - bytes, bytes);
+ if (bytesRead == -1)
+ return {};
+
+ bytes -= bytesRead;
+ }
+
+ return data;
+}
+
+static bool addCookieToFile(QString filename, QString &hostname)
+{
+ QByteArray cookie = getRandomData(16);
+ char *displayNumber = getenv("DISPLAY");
+
+ if(displayNumber == nullptr || displayNumber[0] == '\0' || cookie.count() != 16) {
+ return false;
+ }
+
+ FILE *authFp = fopen(qPrintable(filename), "wb");
+ if (authFp == nullptr) {
+ return false;
+ }
+
+ char localhost[HOST_NAME_MAX + 1] = "";
+ if (gethostname(localhost, HOST_NAME_MAX) < 0) {
+ strcpy(localhost, "localhost");
+ }
+
+ hostname = QString::fromUtf8(localhost);
+
+ Xauth auth = {};
+ char cookieName[] = "MIT-MAGIC-COOKIE-1";
+
+ auth.family = FamilyLocal;
+ auth.address = localhost;
+ auth.address_length = strlen(auth.address);
+ auth.number = displayNumber + 1;
+ auth.number_length = strlen(auth.number);
+ auth.name = cookieName;
+ auth.name_length = sizeof(cookieName) - 1;
+ auth.data = cookie.data();
+ auth.data_length = cookie.count();
+
+ if (XauWriteAuth(authFp, &auth) == 0) {
+ fclose(authFp);
+ return false;
+ }
+
+ auth.family = FamilyWild;
+ bool success = XauWriteAuth(authFp, &auth) != 0 && fflush(authFp) != EOF;
+
+ fclose(authFp);
+
+ return success;
+}
+
void ApplicationWayland::continueStartupWithX()
{
+ if (!m_xwaylandAuthority.fileName().isEmpty()) {
+ QString hostname;
+ if (addCookieToFile(m_xwaylandAuthority.fileName(), hostname)) {
+ setenv("XAUTHORITY", qPrintable(m_xwaylandAuthority.fileName()), 1);
+ setenv("XAUTHLOCALHOSTNAME", qPrintable(hostname), 1);
+ m_environment.insert(QStringLiteral("XAUTHORITY"), m_xwaylandAuthority.fileName());
+ m_environment.insert(QStringLiteral("XAUTHLOCALHOSTNAME"), hostname);
+ }
+ else {
+ std::cerr << "Could not generate Xauthority entry" << std::endl;
+ // We can't authenticate using it so the server must not see any entries either
+ m_xwaylandAuthority.resize(0);
+ }
+ }
+
createX11Connection();
xcb_connection_t *c = x11Connection();
if (!c) {
@@ -377,11 +470,15 @@ void ApplicationWayland::startXwaylandServer()
env.insert("WAYLAND_SOCKET", QByteArray::number(wlfd));
env.insert("EGL_PLATFORM", QByteArrayLiteral("DRM"));
m_xwaylandProcess->setProcessEnvironment(env);
- m_xwaylandProcess->setArguments({QStringLiteral("-displayfd"),
+ QStringList args{QStringLiteral("-displayfd"),
QString::number(pipeFds[1]),
QStringLiteral("-rootless"),
QStringLiteral("-wm"),
- QString::number(fd)});
+ QString::number(fd)};
+ if (!m_xwaylandAuthority.fileName().isEmpty()) {
+ args << QStringLiteral("-auth") << m_xwaylandAuthority.fileName();
+ }
+ m_xwaylandProcess->setArguments(args);
m_xwaylandFailConnection = connect(m_xwaylandProcess, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this,
[] (QProcess::ProcessError error) {
if (error == QProcess::FailedToStart) {
diff --git a/main_wayland.h b/main_wayland.h
index 31b7ebd55..37f9b2882 100644
--- a/main_wayland.h
+++ b/main_wayland.h
@@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KWIN_MAIN_WAYLAND_H
#include "main.h"
#include <QProcessEnvironment>
+#include <QTemporaryFile>
class QProcess;
@@ -74,6 +75,7 @@ private:
QMetaObject::Connection m_xwaylandFailConnection;
QProcessEnvironment m_environment;
QString m_sessionArgument;
+ QTemporaryFile m_xwaylandAuthority;
};
}
--
2.16.2