Add kwin full source tree, greeter login, zsh, pcid service, and build system improvements
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "wayland/clientconnection.h"
|
||||
#include "wayland/display.h"
|
||||
#include "wayland_server.h"
|
||||
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "KWayland/Client/connection_thread.h"
|
||||
#include "KWayland/Client/registry.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_security_context-0");
|
||||
|
||||
class SecurityContextTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
void testSecurityContext();
|
||||
void testClosedCloseFdOnStartup();
|
||||
};
|
||||
|
||||
void SecurityContextTest::initTestCase()
|
||||
{
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
kwinApp()->start();
|
||||
}
|
||||
|
||||
void SecurityContextTest::init()
|
||||
{
|
||||
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::SecurityContextManagerV1));
|
||||
}
|
||||
|
||||
void SecurityContextTest::cleanup()
|
||||
{
|
||||
Test::destroyWaylandConnection();
|
||||
}
|
||||
|
||||
void SecurityContextTest::testSecurityContext()
|
||||
{
|
||||
// This tests a mock flatpak server creating a Security Context
|
||||
// connecting a client to the newly created server
|
||||
// and making sure everything is torn down after the closeFd is closed
|
||||
auto securityContextManager = Test::waylandSecurityContextManagerV1();
|
||||
QVERIFY(securityContextManager);
|
||||
|
||||
int listenFd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
QVERIFY(listenFd != 0);
|
||||
|
||||
QTemporaryDir tempDir;
|
||||
|
||||
sockaddr_un sockaddr;
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s", tempDir.filePath("socket").toUtf8().constData());
|
||||
qDebug() << "listening socket:" << sockaddr.sun_path;
|
||||
QVERIFY(bind(listenFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == 0);
|
||||
QVERIFY(listen(listenFd, 0) == 0);
|
||||
|
||||
int syncFds[2];
|
||||
QVERIFY(pipe(syncFds) >= 0);
|
||||
int closeFdForClientToKeep = syncFds[0];
|
||||
int closeFdToGiveToKwin = syncFds[1];
|
||||
|
||||
auto securityContext = new QtWayland::wp_security_context_v1(securityContextManager->create_listener(listenFd, closeFdToGiveToKwin));
|
||||
close(closeFdToGiveToKwin);
|
||||
close(listenFd);
|
||||
securityContext->set_instance_id("kde.unitest.instance_id");
|
||||
securityContext->set_app_id("kde.unittest.app_id");
|
||||
securityContext->set_sandbox_engine("test_sandbox_engine");
|
||||
securityContext->commit();
|
||||
securityContext->destroy();
|
||||
delete securityContext;
|
||||
|
||||
qputenv("WAYLAND_DISPLAY", tempDir.filePath("socket").toUtf8());
|
||||
QSignalSpy clientConnectedspy(waylandServer()->display(), &Display::clientConnected);
|
||||
|
||||
// connect a client using the newly created listening socket
|
||||
KWayland::Client::ConnectionThread restrictedClientConnection;
|
||||
QSignalSpy connectedSpy(&restrictedClientConnection, &KWayland::Client::ConnectionThread::connected);
|
||||
QThread restictedClientThread;
|
||||
auto restictedClientThreadQuitter = qScopeGuard([&restictedClientThread]() {
|
||||
restictedClientThread.quit();
|
||||
restictedClientThread.wait();
|
||||
});
|
||||
restrictedClientConnection.moveToThread(&restictedClientThread);
|
||||
restictedClientThread.start();
|
||||
restrictedClientConnection.initConnection();
|
||||
QVERIFY(connectedSpy.wait());
|
||||
|
||||
// verify that our new restricted client is seen by kwin with the right security context
|
||||
QVERIFY(clientConnectedspy.count());
|
||||
QCOMPARE(clientConnectedspy.first().first().value<KWin::ClientConnection *>()->securityContextAppId(), "kde.unittest.app_id");
|
||||
|
||||
// verify that the globals for the restricted client does not contain the security context
|
||||
KWayland::Client::Registry registry;
|
||||
registry.create(&restrictedClientConnection);
|
||||
QSignalSpy interfaceAnnounced(®istry, &KWayland::Client::Registry::interfaceAnnounced);
|
||||
QSignalSpy allAnnouncedSpy(®istry, &KWayland::Client::Registry::interfacesAnnounced);
|
||||
registry.setup();
|
||||
QVERIFY(allAnnouncedSpy.wait());
|
||||
for (auto interfaceSignal : interfaceAnnounced) {
|
||||
QVERIFY(interfaceSignal.first().toString() != "wp_security_context_manager_v1");
|
||||
}
|
||||
|
||||
// close the mock flatpak closeFDs
|
||||
close(closeFdForClientToKeep);
|
||||
|
||||
// security context properties should have not changed after close-fd is closed
|
||||
QVERIFY(Test::waylandSync());
|
||||
QCOMPARE(clientConnectedspy.first().first().value<KWin::ClientConnection *>()->securityContextAppId(), "kde.unittest.app_id");
|
||||
|
||||
// new clients can't connect anymore
|
||||
KWayland::Client::ConnectionThread restrictedClientConnection2;
|
||||
QSignalSpy connectedSpy2(&restrictedClientConnection2, &KWayland::Client::ConnectionThread::connected);
|
||||
QSignalSpy failedSpy2(&restrictedClientConnection2, &KWayland::Client::ConnectionThread::failed);
|
||||
QThread restictedClientThread2;
|
||||
auto restictedClientThreadQuitter2 = qScopeGuard([&restictedClientThread2]() {
|
||||
restictedClientThread2.quit();
|
||||
restictedClientThread2.wait();
|
||||
});
|
||||
restrictedClientConnection2.moveToThread(&restictedClientThread2);
|
||||
restictedClientThread2.start();
|
||||
restrictedClientConnection2.initConnection();
|
||||
QVERIFY(failedSpy2.wait());
|
||||
QVERIFY(connectedSpy2.isEmpty());
|
||||
}
|
||||
|
||||
void SecurityContextTest::testClosedCloseFdOnStartup()
|
||||
{
|
||||
// This tests what would happen if the closeFd is already closed when kwin processes the security context
|
||||
auto securityContextManager = Test::waylandSecurityContextManagerV1();
|
||||
QVERIFY(securityContextManager);
|
||||
|
||||
int listenFd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
QVERIFY(listenFd != 0);
|
||||
|
||||
QTemporaryDir tempDir;
|
||||
|
||||
sockaddr_un sockaddr;
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s", tempDir.filePath("socket").toUtf8().constData());
|
||||
qDebug() << "listening socket:" << sockaddr.sun_path;
|
||||
QVERIFY(bind(listenFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == 0);
|
||||
QVERIFY(listen(listenFd, 0) == 0);
|
||||
|
||||
int syncFds[2];
|
||||
QVERIFY(pipe(syncFds) >= 0);
|
||||
int closeFdForClientToKeep = syncFds[0];
|
||||
int closeFdToGiveToKwin = syncFds[1];
|
||||
|
||||
close(closeFdForClientToKeep); // closes the connection
|
||||
|
||||
auto securityContext = new QtWayland::wp_security_context_v1(securityContextManager->create_listener(listenFd, closeFdToGiveToKwin));
|
||||
close(closeFdToGiveToKwin);
|
||||
close(listenFd);
|
||||
securityContext->set_instance_id("kde.unitest.instance_id");
|
||||
securityContext->set_app_id("kde.unittest.app_id");
|
||||
securityContext->set_sandbox_engine("test_sandbox_engine");
|
||||
securityContext->commit();
|
||||
securityContext->destroy();
|
||||
delete securityContext;
|
||||
|
||||
QVERIFY(Test::waylandSync());
|
||||
|
||||
qputenv("WAYLAND_DISPLAY", tempDir.filePath("socket").toUtf8());
|
||||
QSignalSpy clientConnectedspy(waylandServer()->display(), &Display::clientConnected);
|
||||
|
||||
// new clients can't connect anymore
|
||||
KWayland::Client::ConnectionThread restrictedClientConnection;
|
||||
QSignalSpy connectedSpy(&restrictedClientConnection, &KWayland::Client::ConnectionThread::connected);
|
||||
QSignalSpy failedSpy(&restrictedClientConnection, &KWayland::Client::ConnectionThread::failed);
|
||||
QThread restictedClientThread;
|
||||
auto restictedClientThreadQuitter = qScopeGuard([&restictedClientThread]() {
|
||||
restictedClientThread.quit();
|
||||
restictedClientThread.wait();
|
||||
});
|
||||
restrictedClientConnection.moveToThread(&restictedClientThread);
|
||||
restictedClientThread.start();
|
||||
restrictedClientConnection.initConnection();
|
||||
QVERIFY(failedSpy.wait());
|
||||
QVERIFY(connectedSpy.isEmpty());
|
||||
QVERIFY(clientConnectedspy.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(KWin::SecurityContextTest)
|
||||
#include "security_context_test.moc"
|
||||
Reference in New Issue
Block a user