File 0001-Use-Xauthority-for-Xwayland.patch of Package kwin5
From 8026c9649990d70ebe53c5c7d0c68e74fce28014 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 authorization
Currently Xwayland only looks at the uid of the application connecting to it.
Using Xauthority gives more flexibility here, by having a token which can be
passed around.
Not only does this allow to grant only certain applications the right to
connect to the display (e.g. su user xterm) while keeping other applications
outside, this allows also
starting applications as other users again
---
CMakeLists.txt | 1 +
xwl/xwayland.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++++-
xwl/xwayland.h | 3 ++
3 files changed, 105 insertions(+), 2 deletions(-)
Index: kwin-5.15.80git.20200128T055143~f859c2184/CMakeLists.txt
===================================================================
--- kwin-5.15.80git.20200128T055143~f859c2184.orig/CMakeLists.txt 2020-01-28 07:06:54.470652988 +0100
+++ kwin-5.15.80git.20200128T055143~f859c2184/CMakeLists.txt 2020-01-28 07:07:01.953123505 +0100
@@ -605,6 +605,7 @@
${X11_ICE_LIB}
${X11_SM_LIB}
${X11_X11_LIB}
+ ${X11_Xau_LIB}
)
set(kwin_XCB_LIBS
Index: kwin-5.15.80git.20200128T055143~f859c2184/xwl/xwayland.cpp
===================================================================
--- kwin-5.15.80git.20200128T055143~f859c2184.orig/xwl/xwayland.cpp 2020-01-28 07:06:54.470652988 +0100
+++ kwin-5.15.80git.20200128T055143~f859c2184/xwl/xwayland.cpp 2020-01-28 07:10:26.978420516 +0100
@@ -48,6 +48,8 @@
#include <sys/socket.h>
#include <iostream>
+#include <X11/Xauth.h>
+
static void readDisplay(int pipe)
{
QFile readPipe;
@@ -107,8 +109,84 @@
s_self = nullptr;
}
+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 Xwayland::init()
{
+ 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;
+ }
+
int pipeFds[2];
if (pipe(pipeFds) != 0) {
std::cerr << "FATAL ERROR failed to create pipe to start Xwayland " << std::endl;
@@ -150,11 +228,15 @@
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, &QProcess::errorOccurred, this,
[this] (QProcess::ProcessError error) {
if (error == QProcess::FailedToStart) {
@@ -186,6 +268,23 @@
void Xwayland::createX11Connection()
{
+ 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);
+ auto env = m_app->processStartupEnvironment();
+ env.insert(QStringLiteral("XAUTHORITY"), m_xwaylandAuthority.fileName());
+ env.insert(QStringLiteral("XAUTHLOCALHOSTNAME"), hostname);
+ m_app->setProcessStartupEnvironment(env);
+ }
+ 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);
+ }
+ }
+
int screenNumber = 0;
xcb_connection_t *c = nullptr;
if (m_xcbConnectionFd == -1) {
Index: kwin-5.15.80git.20200128T055143~f859c2184/xwl/xwayland.h
===================================================================
--- kwin-5.15.80git.20200128T055143~f859c2184.orig/xwl/xwayland.h 2020-01-28 07:06:54.470652988 +0100
+++ kwin-5.15.80git.20200128T055143~f859c2184/xwl/xwayland.h 2020-01-28 07:07:01.953123505 +0100
@@ -23,6 +23,7 @@
#include "xwayland_interface.h"
#include <xcb/xproto.h>
+#include <QTemporaryFile>
class QProcess;
@@ -74,6 +75,8 @@
const xcb_query_extension_reply_t *m_xfixes = nullptr;
DataBridge *m_dataBridge = nullptr;
+ QTemporaryFile m_xwaylandAuthority;
+
ApplicationWaylandAbstract *m_app;
Q_DISABLE_COPY(Xwayland)