From bac9d554f12a3793a6909169aeb4d2398f44b5a8 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Wed, 18 Nov 2020 16:41:16 +0000 Subject: [PATCH] Move m_display construction to the constructor We will always create one, this resolves potential to call a getter on a null object. Requires some code shuffling. --- wayland_server.cpp | 195 ++++++++++++++++++++++----------------------- 1 file changed, 97 insertions(+), 98 deletions(-) diff --git a/wayland_server.cpp b/wayland_server.cpp index 850057e48a..c3629e62c2 100644 --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -88,8 +88,102 @@ namespace KWin KWIN_SINGLETON_FACTORY(WaylandServer) +class KWinDisplay : public KWaylandServer::FilteredDisplay +{ +public: + KWinDisplay(QObject *parent) + : KWaylandServer::FilteredDisplay(parent) + {} + + static QByteArray sha256(const QString &fileName) + { + QFile f(fileName); + if (f.open(QFile::ReadOnly)) { + QCryptographicHash hash(QCryptographicHash::Sha256); + if (hash.addData(&f)) { + return hash.result(); + } + } + return QByteArray(); + } + + bool isTrustedOrigin(KWaylandServer::ClientConnection *client) const { + const auto fullPathSha = sha256(client->executablePath()); + const auto localSha = sha256(QLatin1String("/proc/") + QString::number(client->processId()) + QLatin1String("/exe")); + const bool trusted = !localSha.isEmpty() && fullPathSha == localSha; + + if (!trusted) { + qCWarning(KWIN_CORE) << "Could not trust" << client->executablePath() << "sha" << localSha << fullPathSha; + } + + return trusted; + } + + QStringList fetchRequestedInterfaces(KWaylandServer::ClientConnection *client) const { + return KWin::fetchRequestedInterfaces(client->executablePath()); + } + + const QSet interfacesBlackList = {"org_kde_kwin_remote_access_manager", "org_kde_plasma_window_management", "org_kde_kwin_fake_input", "org_kde_kwin_keystate", "zkde_screencast_unstable_v1"}; + + const QSet inputmethodInterfaces = { "zwp_input_panel_v1", "zwp_input_method_v1" }; + + QSet m_reported; + + bool allowInterface(KWaylandServer::ClientConnection *client, const QByteArray &interfaceName) override { + if (client->processId() == getpid()) { + return true; + } + + if (client != waylandServer()->inputMethodConnection() && inputmethodInterfaces.contains(interfaceName)) { + return false; + } + + if (!interfacesBlackList.contains(interfaceName)) { + return true; + } + + if (client->executablePath().isEmpty()) { + qCWarning(KWIN_CORE) << "Could not identify process with pid" << client->processId(); + return false; + } + + { + auto requestedInterfaces = client->property("requestedInterfaces"); + if (requestedInterfaces.isNull()) { + requestedInterfaces = fetchRequestedInterfaces(client); + client->setProperty("requestedInterfaces", requestedInterfaces); + } + if (!requestedInterfaces.toStringList().contains(QString::fromUtf8(interfaceName))) { + if (KWIN_CORE().isDebugEnabled()) { + const QString id = client->executablePath() + QLatin1Char('|') + QString::fromUtf8(interfaceName); + if (!m_reported.contains({id})) { + m_reported.insert(id); + qCDebug(KWIN_CORE) << "Interface" << interfaceName << "not in X-KDE-Wayland-Interfaces of" << client->executablePath(); + } + } + return false; + } + } + + { + auto trustedOrigin = client->property("isPrivileged"); + if (trustedOrigin.isNull()) { + trustedOrigin = isTrustedOrigin(client); + client->setProperty("isPrivileged", trustedOrigin); + } + + if (!trustedOrigin.toBool()) { + return false; + } + } + qCDebug(KWIN_CORE) << "authorized" << client->executablePath() << interfaceName; + return true; + } +}; + WaylandServer::WaylandServer(QObject *parent) : QObject(parent) + , m_display(new KWinDisplay(this)) { qRegisterMetaType(); } @@ -136,11 +230,9 @@ void WaylandServer::terminateClientConnections() { destroyInternalConnection(); destroyInputMethodConnection(); - if (m_display) { - const auto connections = m_display->connections(); - for (auto it = connections.begin(); it != connections.end(); ++it) { - (*it)->destroy(); - } + const auto connections = m_display->connections(); + for (auto it = connections.begin(); it != connections.end(); ++it) { + (*it)->destroy(); } } @@ -233,99 +325,6 @@ AbstractWaylandOutput *WaylandServer::findOutput(KWaylandServer::OutputInterface return outputFound; } -class KWinDisplay : public KWaylandServer::FilteredDisplay -{ -public: - KWinDisplay(QObject *parent) - : KWaylandServer::FilteredDisplay(parent) - {} - - static QByteArray sha256(const QString &fileName) - { - QFile f(fileName); - if (f.open(QFile::ReadOnly)) { - QCryptographicHash hash(QCryptographicHash::Sha256); - if (hash.addData(&f)) { - return hash.result(); - } - } - return QByteArray(); - } - - bool isTrustedOrigin(KWaylandServer::ClientConnection *client) const { - const auto fullPathSha = sha256(client->executablePath()); - const auto localSha = sha256(QLatin1String("/proc/") + QString::number(client->processId()) + QLatin1String("/exe")); - const bool trusted = !localSha.isEmpty() && fullPathSha == localSha; - - if (!trusted) { - qCWarning(KWIN_CORE) << "Could not trust" << client->executablePath() << "sha" << localSha << fullPathSha; - } - - return trusted; - } - - QStringList fetchRequestedInterfaces(KWaylandServer::ClientConnection *client) const { - return KWin::fetchRequestedInterfaces(client->executablePath()); - } - - const QSet interfacesBlackList = {"org_kde_kwin_remote_access_manager", "org_kde_plasma_window_management", "org_kde_kwin_fake_input", "org_kde_kwin_keystate", "zkde_screencast_unstable_v1"}; - - const QSet inputmethodInterfaces = { "zwp_input_panel_v1", "zwp_input_method_v1" }; - - QSet m_reported; - - bool allowInterface(KWaylandServer::ClientConnection *client, const QByteArray &interfaceName) override { - if (client->processId() == getpid()) { - return true; - } - - if (client != waylandServer()->inputMethodConnection() && inputmethodInterfaces.contains(interfaceName)) { - return false; - } - - if (!interfacesBlackList.contains(interfaceName)) { - return true; - } - - if (client->executablePath().isEmpty()) { - qCWarning(KWIN_CORE) << "Could not identify process with pid" << client->processId(); - return false; - } - - { - auto requestedInterfaces = client->property("requestedInterfaces"); - if (requestedInterfaces.isNull()) { - requestedInterfaces = fetchRequestedInterfaces(client); - client->setProperty("requestedInterfaces", requestedInterfaces); - } - if (!requestedInterfaces.toStringList().contains(QString::fromUtf8(interfaceName))) { - if (KWIN_CORE().isDebugEnabled()) { - const QString id = client->executablePath() + QLatin1Char('|') + QString::fromUtf8(interfaceName); - if (!m_reported.contains({id})) { - m_reported.insert(id); - qCDebug(KWIN_CORE) << "Interface" << interfaceName << "not in X-KDE-Wayland-Interfaces of" << client->executablePath(); - } - } - return false; - } - } - - { - auto trustedOrigin = client->property("isPrivileged"); - if (trustedOrigin.isNull()) { - trustedOrigin = isTrustedOrigin(client); - client->setProperty("isPrivileged", trustedOrigin); - } - - if (!trustedOrigin.toBool()) { - return false; - } - } - qCDebug(KWIN_CORE) << "authorized" << client->executablePath() << interfaceName; - return true; - } -}; - bool WaylandServer::start() { return m_display->start();