diff --git a/0001-xwayland-Generate-Xauthority-file.patch b/0001-xwayland-Generate-Xauthority-file.patch new file mode 100644 index 0000000..c9d8892 --- /dev/null +++ b/0001-xwayland-Generate-Xauthority-file.patch @@ -0,0 +1,269 @@ +From e1e75b594a629991037e4f721eca6a4ed4e03c3c Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Mon, 8 Feb 2021 13:57:12 +0200 +Subject: [PATCH] xwayland: Generate Xauthority file + +This allows running Xwayland apps as root. Xwayland started with an +empty Xauthority file. After kwin has received the display number, the +file is updated with an actual authority entry. + +BUG: 432625 + +(cherry picked from commit c427aaebbfecc2704539a20e42738e71c3fc55b1) +--- + autotests/integration/kwin_wayland_test.cpp | 1 + + main_wayland.cpp | 1 + + xwl/xwayland.cpp | 103 +++++++++++++++++--- + xwl/xwayland.h | 9 +- + 4 files changed, 98 insertions(+), 16 deletions(-) + +diff --git a/autotests/integration/kwin_wayland_test.cpp b/autotests/integration/kwin_wayland_test.cpp +index 661eafc12..3e0ed8308 100644 +--- a/autotests/integration/kwin_wayland_test.cpp ++++ b/autotests/integration/kwin_wayland_test.cpp +@@ -104,6 +104,7 @@ void WaylandTestApplication::performStartup() + environment.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland")); + environment.remove("DISPLAY"); + environment.remove("WAYLAND_DISPLAY"); ++ environment.remove("XAUTHORITY"); + QProcess *p = new Process(this); + p->setProcessChannelMode(QProcess::ForwardedErrorChannel); + connect(p, qOverload(&QProcess::finished), this, +diff --git a/main_wayland.cpp b/main_wayland.cpp +index 8e6434bbf..2070e7969 100644 +--- a/main_wayland.cpp ++++ b/main_wayland.cpp +@@ -270,6 +270,7 @@ void ApplicationWayland::startInputMethod(const QString &executable) + environment.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland")); + environment.remove("DISPLAY"); + environment.remove("WAYLAND_DISPLAY"); ++ environment.remove("XAUTHORITY"); + + m_inputMethodProcess = new Process(this); + m_inputMethodProcess->setProcessChannelMode(QProcess::ForwardedErrorChannel); +diff --git a/xwl/xwayland.cpp b/xwl/xwayland.cpp +index 06dca9725..cdc4f50ab 100644 +--- a/xwl/xwayland.cpp ++++ b/xwl/xwayland.cpp +@@ -23,7 +23,10 @@ + #include + + #include ++#include + #include ++#include ++#include + #include + #include + +@@ -39,22 +42,20 @@ + #include + #include + +-static QByteArray readDisplay(int pipe) ++static int readDisplay(int pipe) + { +- QByteArray displayName; ++ int display = -1; + QFile readPipe; + + if (!readPipe.open(pipe, QIODevice::ReadOnly)) { + qCWarning(KWIN_XWL) << "Failed to open X11 display name pipe:" << readPipe.errorString(); + } else { +- displayName = readPipe.readLine(); +- displayName.prepend(QByteArrayLiteral(":")); +- displayName.remove(displayName.size() - 1, 1); ++ display = readPipe.readLine().trimmed().toInt(); + } + + // close our pipe + close(pipe); +- return displayName; ++ return display; + } + + namespace KWin +@@ -119,6 +120,12 @@ void Xwayland::start() + return; + } + ++ if (!createXauthorityFile()) { ++ qCWarning(KWIN_XWL) << "Failed to create an Xauthority file"; ++ emit errorOccurred(); ++ return; ++ } ++ + m_xcbConnectionFd = sx[0]; + m_displayFileDescriptor = pipeFds[0]; + +@@ -135,8 +142,8 @@ void Xwayland::start() + m_xwaylandProcess->setArguments({QStringLiteral("-displayfd"), + QString::number(pipeFds[1]), + QStringLiteral("-rootless"), +- QStringLiteral("-wm"), +- QString::number(fd)}); ++ QStringLiteral("-wm"), QString::number(fd), ++ QStringLiteral("-auth"), m_authorityFile->fileName()}); + connect(m_xwaylandProcess, &QProcess::errorOccurred, this, &Xwayland::handleXwaylandError); + connect(m_xwaylandProcess, &QProcess::started, this, &Xwayland::handleXwaylandStarted); + connect(m_xwaylandProcess, QOverload::of(&QProcess::finished), +@@ -172,6 +179,7 @@ void Xwayland::stop() + delete m_xwaylandProcess; + m_xwaylandProcess = nullptr; + ++ m_authorityFile.reset(); + waylandServer()->destroyXWaylandConnection(); // This one must be destroyed last! + + m_app->setClosingX11Connection(false); +@@ -232,8 +240,8 @@ void Xwayland::uninstallSocketNotifier() + + void Xwayland::handleXwaylandStarted() + { +- m_watcher = new QFutureWatcher(this); +- connect(m_watcher, &QFutureWatcher::finished, this, &Xwayland::handleXwaylandReady); ++ m_watcher = new QFutureWatcher(this); ++ connect(m_watcher, &QFutureWatcher::finished, this, &Xwayland::handleXwaylandReady); + m_watcher->setFuture(QtConcurrent::run(readDisplay, m_displayFileDescriptor)); + } + +@@ -304,7 +312,7 @@ void Xwayland::handleXwaylandError(QProcess::ProcessError error) + + void Xwayland::handleXwaylandReady() + { +- m_displayName = m_watcher->result(); ++ m_display = m_watcher->result(); + + m_watcher->deleteLater(); + m_watcher = nullptr; +@@ -314,8 +322,12 @@ void Xwayland::handleXwaylandReady() + return; + } + +- qCInfo(KWIN_XWL) << "Xwayland server started on display" << m_displayName; +- qputenv("DISPLAY", m_displayName); ++ const QByteArray displayName = ':' + QByteArray::number(m_display); ++ updateXauthorityFile(); ++ ++ qCInfo(KWIN_XWL) << "Xwayland server started on display" << displayName; ++ qputenv("DISPLAY", displayName); ++ qputenv("XAUTHORITY", m_authorityFile->fileName().toUtf8()); + + // create selection owner for WM_S0 - magic X display number expected by XWayland + KSelectionOwner owner("WM_S0", kwinApp()->x11Connection(), kwinApp()->x11RootWindow()); +@@ -324,7 +336,8 @@ void Xwayland::handleXwaylandReady() + DataBridge::create(this); + + auto env = m_app->processStartupEnvironment(); +- env.insert(QStringLiteral("DISPLAY"), m_displayName); ++ env.insert(QStringLiteral("DISPLAY"), displayName); ++ env.insert(QStringLiteral("XAUTHORITY"), m_authorityFile->fileName()); + m_app->setProcessStartupEnvironment(env); + + emit started(); +@@ -385,6 +398,68 @@ void Xwayland::destroyX11Connection() + emit m_app->x11ConnectionChanged(); + } + ++bool Xwayland::createXauthorityFile() ++{ ++ const QString runtimeDirectory = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); ++ const QString fileNameTemplate = QStringLiteral(".Xauthority-kwin_wayland.XXXXXX"); ++ ++ QScopedPointer authorityFile(new QTemporaryFile(runtimeDirectory + '/' + fileNameTemplate)); ++ if (!authorityFile->open()) { ++ return false; ++ } ++ ++ m_authorityFile.reset(authorityFile.take()); ++ return true; ++} ++ ++static void writeXauthorityEntry(QDataStream *stream, quint16 family, ++ const QByteArray &address, const QByteArray &display, ++ const QByteArray &name, const QByteArray &cookie) ++{ ++ *stream << quint16(family); ++ ++ *stream << quint16(address.size()); ++ stream->writeRawData(address.constData(), address.size()); ++ ++ *stream << quint16(display.size()); ++ stream->writeRawData(display.constData(), display.size()); ++ ++ *stream << quint16(name.size()); ++ stream->writeRawData(name.constData(), name.size()); ++ ++ *stream << quint16(cookie.size()); ++ stream->writeRawData(cookie.constData(), cookie.size()); ++} ++ ++static QByteArray generateXauthorityCookie() ++{ ++ QByteArray cookie; ++ cookie.resize(16); // Cookie must be 128bits ++ ++ QRandomGenerator *generator = QRandomGenerator::system(); ++ for (int i = 0; i < cookie.size(); ++i) { ++ cookie[i] = uint8_t(generator->bounded(256)); ++ } ++ return cookie; ++} ++ ++void Xwayland::updateXauthorityFile() ++{ ++ const quint16 family = 256; // FamilyLocal ++ ++ const QByteArray address = QHostInfo::localHostName().toUtf8(); ++ const QByteArray display = QByteArray::number(m_display); ++ const QByteArray name = QByteArrayLiteral("MIT-MAGIC-COOKIE-1"); ++ const QByteArray cookie = generateXauthorityCookie(); ++ ++ QDataStream stream(m_authorityFile.data()); ++ stream.setByteOrder(QDataStream::BigEndian); ++ ++ writeXauthorityEntry(&stream, family, address, display, name, cookie); ++ ++ m_authorityFile->flush(); ++} ++ + DragEventReply Xwayland::dragMoveFilter(Toplevel *target, const QPoint &pos) + { + DataBridge *bridge = DataBridge::self(); +diff --git a/xwl/xwayland.h b/xwl/xwayland.h +index 0254188e5..0b827fca4 100644 +--- a/xwl/xwayland.h ++++ b/xwl/xwayland.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + namespace KWin + { +@@ -95,6 +96,9 @@ private: + bool createX11Connection(); + void destroyX11Connection(); + ++ bool createXauthorityFile(); ++ void updateXauthorityFile(); ++ + DragEventReply dragMoveFilter(Toplevel *target, const QPoint &pos) override; + + int m_displayFileDescriptor = -1; +@@ -102,9 +106,10 @@ private: + QProcess *m_xwaylandProcess = nullptr; + QSocketNotifier *m_socketNotifier = nullptr; + QTimer *m_resetCrashCountTimer = nullptr; +- QByteArray m_displayName; +- QFutureWatcher *m_watcher = nullptr; ++ int m_display = -1; ++ QFutureWatcher *m_watcher = nullptr; + ApplicationWaylandAbstract *m_app; ++ QScopedPointer m_authorityFile; + int m_crashCount = 0; + + Q_DISABLE_COPY(Xwayland) +-- +2.29.2 + diff --git a/kwin.spec b/kwin.spec index f35da17..2626689 100644 --- a/kwin.spec +++ b/kwin.spec @@ -17,7 +17,7 @@ Name: kwin Version: 5.20.90 -Release: 3%{?dist} +Release: 4%{?dist} Summary: KDE Window manager # all sources are effectively GPLv2+, except for: @@ -37,9 +37,13 @@ URL: https://userbase.kde.org/KWin Source0: http://download.kde.org/%{stable}/plasma/%{version}/%{name}-%{version}.tar.xz ## upstream patches - Patch14: 0014-Fix-the-systemd-wayland-boot.patch +## proposed patches +### From: https://invent.kde.org/plasma/kwin/-/merge_requests/665 +Patch51: 0001-xwayland-Generate-Xauthority-file.patch + + # Base BuildRequires: extra-cmake-modules BuildRequires: kf5-rpm-macros @@ -360,8 +364,11 @@ make test ARGS="--output-on-failure --timeout 10" -C %{_target_platform} ||: %changelog +* Mon Feb 08 2021 Neal Gompa - 5.20.90-4 +- Add patch to ensure Xauthority file is generated for Wayland (rhbz#1921947) + * Thu Jan 28 2021 Rex Dieter - 5.20.90-3 -- pull in upstream wayland fix (#432189) +- pull in upstream wayland fix (kde#432189) - .spec cosmetics - revert BR: make (not needed)