From 4dede9538c44358859dee442dd3c5318c5cab62c Mon Sep 17 00:00:00 2001 From: Albert S Date: Fri, 6 Aug 2021 20:33:01 +0200 Subject: [PATCH 01/13] submodules: add qssb.h --- .gitmodules | 3 +++ submodules/qssb.h | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 submodules/qssb.h diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ba48fd5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/qssb.h"] + path = submodules/qssb.h + url = https://gitea.quitesimple.org/crtxcr/qssb.h diff --git a/submodules/qssb.h b/submodules/qssb.h new file mode 160000 index 0000000..75f607b --- /dev/null +++ b/submodules/qssb.h @@ -0,0 +1 @@ +Subproject commit 75f607bc350354ed31fd0977311917e13241e703 -- 2.47.1 From ebea074fcb47d1ff331a8a10a8577d111e4d7247 Mon Sep 17 00:00:00 2001 From: Albert S Date: Sat, 7 Aug 2021 12:03:35 +0200 Subject: [PATCH 02/13] gui: Begin basic sandboxing --- gui/main.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/gui/main.cpp b/gui/main.cpp index df3ee28..cd8766d 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -1,13 +1,34 @@ #include #include #include +#include #include "mainwindow.h" #include "searchresult.h" #include "pdfpreview.h" #include "../shared/common.h" +#include "../submodules/qssb.h/qssb.h" int main(int argc, char *argv[]) { + struct qssb_policy *policy = qssb_init_policy(); + std::string appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); + std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString(); + + policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER; + qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE, "/"); + qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE, + appDataLocation.c_str()); + qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE, + cacheDataLocation.c_str()); + + int ret = qssb_enable_policy(policy); + if(ret != 0) + { + qDebug() << "Failed to establish sandbox"; + return 1; + } + qssb_free_policy(policy); + Common::setupAppInfo(); QApplication a(argc, argv); try -- 2.47.1 From ad84c8acf71d3f165993d3ff7d299d5e3048df93 Mon Sep 17 00:00:00 2001 From: Albert S Date: Sat, 7 Aug 2021 18:38:23 +0200 Subject: [PATCH 03/13] cli: moved processing of file content into sandboxed subprocess --- cli/cli.pro | 3 ++ cli/filesaver.cpp | 54 ++++++++++--------- cli/main.cpp | 15 ++++++ cli/pagedata.cpp | 13 +++++ cli/pagedata.h | 10 ++++ cli/processor.h | 2 + cli/sandboxedprocessor.cpp | 103 +++++++++++++++++++++++++++++++++++++ cli/sandboxedprocessor.h | 23 +++++++++ 8 files changed, 198 insertions(+), 25 deletions(-) create mode 100644 cli/pagedata.cpp create mode 100644 cli/sandboxedprocessor.cpp create mode 100644 cli/sandboxedprocessor.h diff --git a/cli/cli.pro b/cli/cli.pro index 9c985c7..2430ed3 100644 --- a/cli/cli.pro +++ b/cli/cli.pro @@ -18,10 +18,12 @@ LIBS += -luchardet -lpoppler-qt5 -lquazip5 SOURCES += \ main.cpp \ encodingdetector.cpp \ + pagedata.cpp \ processor.cpp \ pdfprocessor.cpp \ defaulttextprocessor.cpp \ commandadd.cpp \ + sandboxedprocessor.cpp \ tagstripperprocessor.cpp \ nothingprocessor.cpp \ odtprocessor.cpp \ @@ -44,6 +46,7 @@ HEADERS += \ defaulttextprocessor.h \ command.h \ commandadd.h \ + sandboxedprocessor.h \ tagstripperprocessor.h \ nothingprocessor.h \ odtprocessor.h \ diff --git a/cli/filesaver.cpp b/cli/filesaver.cpp index 2ae1c14..a0b2d94 100644 --- a/cli/filesaver.cpp +++ b/cli/filesaver.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "filesaver.h" #include "processor.h" @@ -13,18 +14,6 @@ #include "odsprocessor.h" #include "utils.h" #include "logger.h" -static DefaultTextProcessor *defaultTextProcessor = new DefaultTextProcessor(); -static TagStripperProcessor *tagStripperProcessor = new TagStripperProcessor(); -static NothingProcessor *nothingProcessor = new NothingProcessor(); -static OdtProcessor *odtProcessor = new OdtProcessor(); -static OdsProcessor *odsProcessor = new OdsProcessor(); - -static QMap processors{ - {"pdf", new PdfProcessor()}, {"txt", defaultTextProcessor}, {"md", defaultTextProcessor}, - {"py", defaultTextProcessor}, {"xml", nothingProcessor}, {"html", tagStripperProcessor}, - {"java", defaultTextProcessor}, {"js", defaultTextProcessor}, {"cpp", defaultTextProcessor}, - {"c", defaultTextProcessor}, {"sql", defaultTextProcessor}, {"odt", odtProcessor}, - {"ods", odsProcessor}}; FileSaver::FileSaver(SqliteDbService &dbService) { @@ -106,32 +95,47 @@ int FileSaver::processFiles(const QVector paths, std::function pageData; QString absPath = fileInfo.absoluteFilePath(); + int status = -1; if(fileInfo.isFile()) { - try + QProcess process; + QStringList args; + args << "process" << absPath; + process.setProcessChannelMode(QProcess::ForwardedErrorChannel); + process.start("/proc/self/exe", args); + process.waitForStarted(); + process.waitForFinished(); + + /* TODO: This is suboptimal as it eats lots of mem + * but avoids a weird QDataStream/QProcess behaviour + * where it thinks the process has ended when it has not... + * + * Also, there seem to be issues with reads not being blocked, so + * the only reliable way appears to be waiting until the process + * finishes. + */ + QDataStream in(process.readAllStandardOutput()); + while(!in.atEnd()) { - if(processor->PREFERED_DATA_SOURCE == FILEPATH) - { - pageData = processor->process(absPath); - } - else - { - pageData = processor->process(Utils::readFile(absPath)); - } + PageData pd; + in >> pd; + pageData.append(pd); } - catch(LooqsGeneralException &e) + status = process.exitCode(); + if(status != 0) { - Logger::error() << "Error while processing" << absPath << ":" << e.message << Qt::endl; + Logger::error() << "Error while processing" << absPath << ":" + << "Exit code " << status << Qt::endl; + return PROCESSFAIL; } } // Could happen if a file corrupted for example - if(pageData.isEmpty() && processor != nothingProcessor) + if(pageData.isEmpty() && status != NOTHING_PROCESSED) { Logger::error() << "Could not get any content for " << absPath << Qt::endl; } diff --git a/cli/main.cpp b/cli/main.cpp index a490269..9439b1d 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -24,6 +24,7 @@ #include "commandsearch.h" #include "databasefactory.h" #include "logger.h" +#include "sandboxedprocessor.h" #include "../shared/common.h" void printUsage(QString argv0) @@ -59,6 +60,7 @@ int main(int argc, char *argv[]) QCoreApplication app(argc, argv); QStringList args = app.arguments(); QString argv0 = args.takeFirst(); + if(args.length() < 1) { printUsage(argv0); @@ -74,11 +76,24 @@ int main(int argc, char *argv[]) Logger::error() << "Error: " << e.message; return 1; } + qRegisterMetaType(); QString connectionString = Common::databasePath(); DatabaseFactory dbFactory(connectionString); SqliteDbService dbService(dbFactory); QString commandName = args.first(); + if(commandName == "process") + { + if(args.length() < 1) + { + qDebug() << "Filename is required"; + return 1; + } + + QString file = args.at(1); + SandboxedProcessor processor(file); + return processor.process(); + } Command *cmd = commandFromName(commandName, dbService); if(cmd != nullptr) { diff --git a/cli/pagedata.cpp b/cli/pagedata.cpp new file mode 100644 index 0000000..6d7a19e --- /dev/null +++ b/cli/pagedata.cpp @@ -0,0 +1,13 @@ +#include "pagedata.h" + +QDataStream &operator<<(QDataStream &out, const PageData &pd) +{ + out << pd.pagenumber << pd.content; + return out; +} + +QDataStream &operator>>(QDataStream &in, PageData &pd) +{ + in >> pd.pagenumber >> pd.content; + return in; +} diff --git a/cli/pagedata.h b/cli/pagedata.h index d550116..8697d56 100644 --- a/cli/pagedata.h +++ b/cli/pagedata.h @@ -1,6 +1,9 @@ #ifndef PAGEDATA_H #define PAGEDATA_H #include +#include +#include + class PageData { public: @@ -10,10 +13,17 @@ class PageData PageData() { } + PageData(unsigned int pagenumber, QString content) { this->pagenumber = pagenumber; this->content = content; } }; + +Q_DECLARE_METATYPE(PageData); + +QDataStream &operator<<(QDataStream &out, const PageData &pd); +QDataStream &operator>>(QDataStream &in, PageData &pd); + #endif // PAGEDATA_H diff --git a/cli/processor.h b/cli/processor.h index 04bd04a..82f1c27 100644 --- a/cli/processor.h +++ b/cli/processor.h @@ -10,6 +10,8 @@ enum DataSource ARRAY }; +#define NOTHING_PROCESSED 4 + class Processor { public: diff --git a/cli/sandboxedprocessor.cpp b/cli/sandboxedprocessor.cpp new file mode 100644 index 0000000..3341c57 --- /dev/null +++ b/cli/sandboxedprocessor.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +#include "sandboxedprocessor.h" +#include "pdfprocessor.h" +#include "defaulttextprocessor.h" +#include "tagstripperprocessor.h" +#include "nothingprocessor.h" +#include "odtprocessor.h" +#include "odsprocessor.h" +#include "../submodules/qssb.h/qssb.h" +#include "logger.h" + +static DefaultTextProcessor *defaultTextProcessor = new DefaultTextProcessor(); +static TagStripperProcessor *tagStripperProcessor = new TagStripperProcessor(); +static NothingProcessor *nothingProcessor = new NothingProcessor(); +static OdtProcessor *odtProcessor = new OdtProcessor(); +static OdsProcessor *odsProcessor = new OdsProcessor(); + +static QMap processors{ + {"pdf", new PdfProcessor()}, {"txt", defaultTextProcessor}, {"md", defaultTextProcessor}, + {"py", defaultTextProcessor}, {"xml", nothingProcessor}, {"html", tagStripperProcessor}, + {"java", defaultTextProcessor}, {"js", defaultTextProcessor}, {"cpp", defaultTextProcessor}, + {"c", defaultTextProcessor}, {"sql", defaultTextProcessor}, {"odt", odtProcessor}, + {"ods", odsProcessor}}; + +void SandboxedProcessor::enableSandbox(QString readablePath) +{ + struct qssb_policy *policy = qssb_init_policy(); + + policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER; + + if(!readablePath.isEmpty()) + { + std::string readablePathLocation = readablePath.toStdString(); + qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ, readablePathLocation.c_str()); + } + else + { + policy->no_fs = 1; + } + int ret = qssb_enable_policy(policy); + if(ret != 0) + { + qDebug() << "Failed to establish sandbox: " << ret; + exit(EXIT_FAILURE); + } + qssb_free_policy(policy); +} + +void SandboxedProcessor::printResults(const QVector &pageData) +{ + QFile fsstdout; + fsstdout.open(stdout, QIODevice::WriteOnly); + QDataStream stream(&fsstdout); + + for(const PageData &data : pageData) + { + stream << data; + // fsstdout.flush(); + } + + fsstdout.close(); +} + +int SandboxedProcessor::process() +{ + QFileInfo fileInfo(this->filePath); + Processor *processor = processors.value(fileInfo.suffix(), nothingProcessor); + + if(processor == nothingProcessor) + { + /* Nothing to do */ + return NOTHING_PROCESSED; + } + + QVector pageData; + QString absPath = fileInfo.absoluteFilePath(); + + try + { + if(processor->PREFERED_DATA_SOURCE == FILEPATH) + { + /* Read access to FS needed... doh..*/ + enableSandbox(absPath); + pageData = processor->process(absPath); + } + else + { + QByteArray data = Utils::readFile(absPath); + enableSandbox(); + pageData = processor->process(data); + } + } + catch(LooqsGeneralException &e) + { + Logger::error() << "Error while processing" << absPath << ":" << e.message << Qt::endl; + return 3 /* PROCESSFAIL */; + } + + printResults(pageData); + return 0; +} diff --git a/cli/sandboxedprocessor.h b/cli/sandboxedprocessor.h new file mode 100644 index 0000000..416d2e0 --- /dev/null +++ b/cli/sandboxedprocessor.h @@ -0,0 +1,23 @@ +#ifndef SANDBOXEDPROCESSOR_H +#define SANDBOXEDPROCESSOR_H +#include +#include "pagedata.h" + +class SandboxedProcessor +{ + private: + QString filePath; + + void enableSandbox(QString readablePath = ""); + void printResults(const QVector &pageData); + + public: + SandboxedProcessor(QString filepath) + { + this->filePath = filepath; + } + + int process(); +}; + +#endif // SANDBOXEDPROCESSOR_H -- 2.47.1 From 530ad9c3349981ee59c8cd5e47046ab9aeee54b0 Mon Sep 17 00:00:00 2001 From: Albert S Date: Sun, 8 Aug 2021 17:05:43 +0200 Subject: [PATCH 04/13] pdfworker: Remove dead code --- gui/pdfworker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/gui/pdfworker.cpp b/gui/pdfworker.cpp index d4a683f..b300f21 100644 --- a/gui/pdfworker.cpp +++ b/gui/pdfworker.cpp @@ -103,6 +103,5 @@ QFuture PdfWorker::generatePreviews(const QVector path double scaleX = QGuiApplication::primaryScreen()->physicalDotsPerInchX() * scalefactor; double scaleY = QGuiApplication::primaryScreen()->physicalDotsPerInchY() * scalefactor; - QSettings setting; return QtConcurrent::mapped(previews, Renderer(scaleX, scaleY, wordsToHighlight)); } -- 2.47.1 From 3e387b99f8f67dc0b83eaca7d5f2e7d84e745bae Mon Sep 17 00:00:00 2001 From: Albert S Date: Wed, 11 Aug 2021 21:05:39 +0200 Subject: [PATCH 05/13] README: Mention sandboxing --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bb76fb0..2822eb2 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,12 @@ Currently, this allows you search all indexed pdfs and take a look at the pages Coming soon™ -## Goals +## Goals and principles * **Find & Preview**. Instead of merely telling you where your search phrase has been found, it should also render the corresponding portion/pages of the documents and highlight the searched words. * **No daemons**. As other solutions are prone to have annoying daemons running that eat system resources away, this solution should make do without daemons if possible. - * **Easy setup**. Similiarly, there should be no need for heavy-weight databases. Instead, this solution tries to squeeze out the most from simple approaches. In particular, it relies on sqlite. + * **Easy setup**. Similiarly, there should be no need for heavy-weight databases. Instead, this solution tries to squeeze out the most from simple approaches. In particular, it relies on sqlite. * **GUI & CLI**. Provide CLI interfaces and GUI interfaces - + * **Sandboxing**. As reading and rendering lots of formats naturally opens the door for security bugs, those tasks are offloaded to small, sandboxed sub-processes to mitigate the effect of exploited vulnerabilities. ## Build ### Ubuntu 21.04 -- 2.47.1 From 890925929a6fada9452fc957c57a29b1bf479d9d Mon Sep 17 00:00:00 2001 From: Albert S Date: Tue, 28 Sep 2021 21:44:09 +0200 Subject: [PATCH 06/13] GUI: Begin IPC mechanism to open files despite sandboxing --- gui/gui.pro | 7 +++- gui/ipc.h | 9 +++++ gui/ipcclient.cpp | 27 ++++++++++++++ gui/ipcclient.h | 18 ++++++++++ gui/ipcserver.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++ gui/ipcserver.h | 21 +++++++++++ gui/main.cpp | 38 ++++++++++++++++++-- gui/mainwindow.cpp | 51 +++++++++++---------------- gui/mainwindow.h | 8 ++++- shared/shared.pro | 2 ++ submodules/qssb.h | 2 +- 11 files changed, 235 insertions(+), 36 deletions(-) create mode 100644 gui/ipc.h create mode 100644 gui/ipcclient.cpp create mode 100644 gui/ipcclient.h create mode 100644 gui/ipcserver.cpp create mode 100644 gui/ipcserver.h diff --git a/gui/gui.pro b/gui/gui.pro index 5417c1f..e97e05c 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core concurrent gui +QT += core concurrent gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 @@ -23,6 +23,8 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + ipcclient.cpp \ + ipcserver.cpp \ main.cpp \ mainwindow.cpp \ pdfworker.cpp \ @@ -30,6 +32,9 @@ SOURCES += \ clicklabel.cpp HEADERS += \ + ipc.h \ + ipcclient.h \ + ipcserver.h \ mainwindow.h \ pdfworker.h \ pdfpreview.h \ diff --git a/gui/ipc.h b/gui/ipc.h new file mode 100644 index 0000000..f1ef8a3 --- /dev/null +++ b/gui/ipc.h @@ -0,0 +1,9 @@ +#ifndef IPC_H +#define IPC_H + +enum IPCCommand +{ + DocOpen, + FileOpen +}; +#endif // IPC_H diff --git a/gui/ipcclient.cpp b/gui/ipcclient.cpp new file mode 100644 index 0000000..9f29f6b --- /dev/null +++ b/gui/ipcclient.cpp @@ -0,0 +1,27 @@ +#include +#include "ipcclient.h" + +IPCClient::IPCClient(QString socketPath) +{ + this->socketPath = socketPath; +} + +bool IPCClient::sendCommand(IPCCommand command, QStringList args) +{ + bool result = false; + QLocalSocket socket; + socket.connectToServer(socketPath); + if(socket.isOpen() && socket.isWritable()) + { + QDataStream stream(&socket); + stream << command; + stream << args; + socket.flush(); + result = true; + } + else + { + qDebug() << "Not connected to IPC server"; + } + return result; +} diff --git a/gui/ipcclient.h b/gui/ipcclient.h new file mode 100644 index 0000000..cd3eb2c --- /dev/null +++ b/gui/ipcclient.h @@ -0,0 +1,18 @@ +#ifndef IPCCLIENT_H +#define IPCCLIENT_H +#include +#include +#include +#include "ipc.h" + +class IPCClient +{ + private: + QString socketPath; + + public: + IPCClient(QString socketPath); + bool sendCommand(IPCCommand command, QStringList args); +}; + +#endif // IPCCLIENT_H diff --git a/gui/ipcserver.cpp b/gui/ipcserver.cpp new file mode 100644 index 0000000..01ec349 --- /dev/null +++ b/gui/ipcserver.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ipcserver.h" + +IpcServer::IpcServer() +{ + connect(&this->spawningServer, &QLocalServer::newConnection, this, &IpcServer::spawnerNewConnection); +} + +bool IpcServer::startSpawner(QString socketPath) +{ + QFile::remove(socketPath); + return this->spawningServer.listen(socketPath); +} + +bool IpcServer::docOpen(QString path, int pagenum) +{ + QSettings settings; + QString command = settings.value("pdfviewer").toString(); + if(command != "" && command.contains("%p") && command.contains("%f")) + { + QStringList splitted = command.split(" "); + if(splitted.size() > 1) + { + QString cmd = splitted[0]; + QStringList args = splitted.mid(1); + args.replaceInStrings("%f", path); + args.replaceInStrings("%p", QString::number(pagenum)); + + QProcess::startDetached(cmd, args); + } + } + else + { + QDesktopServices::openUrl(QUrl::fromLocalFile(path)); + } + return true; +} + +bool IpcServer::fileOpen(QString path) +{ + return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); +} + +void IpcServer::spawnerNewConnection() +{ + QScopedPointer socket{this->spawningServer.nextPendingConnection()}; + if(!socket.isNull()) + { + if(!socket->waitForReadyRead()) + { + return; + } + QDataStream stream(socket.get()); + IPCCommand command; + QStringList args; + stream >> command; + stream >> args; + if(args.size() < 1) + { + stream << "invalid"; + return; + } + if(command == DocOpen) + { + if(args.size() < 2) + { + stream << "invalid"; + return; + } + docOpen(args[0], args[2].toInt()); + } + if(command == FileOpen) + { + if(args.size() < 1) + { + stream << "invalid"; + return; + } + fileOpen(args[0]); + } + } +} diff --git a/gui/ipcserver.h b/gui/ipcserver.h new file mode 100644 index 0000000..7f86a8b --- /dev/null +++ b/gui/ipcserver.h @@ -0,0 +1,21 @@ +#ifndef IPCSERVER_H +#define IPCSERVER_H +#include +#include +#include "ipc.h" +class IpcServer : public QObject +{ + Q_OBJECT + private: + QLocalServer spawningServer; + bool docOpen(QString path, int pagenum); + bool fileOpen(QString path); + private slots: + void spawnerNewConnection(); + + public: + IpcServer(); + bool startSpawner(QString socketPath); +}; + +#endif // IPCSERVER_H diff --git a/gui/main.cpp b/gui/main.cpp index cd8766d..06dcfeb 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -2,19 +2,51 @@ #include #include #include +#include + #include "mainwindow.h" #include "searchresult.h" #include "pdfpreview.h" #include "../shared/common.h" #include "../submodules/qssb.h/qssb.h" +#include "ipcserver.h" int main(int argc, char *argv[]) { + QString socketPath = "/tmp/looqs-spawner"; + if(argc > 1) + { + QApplication a(argc, argv); + QString arg = argv[1]; + if(arg == "ipc") + { + IpcServer *ipcserver = new IpcServer(); + qDebug() << "Launching ipc"; + if(!ipcserver->startSpawner(socketPath)) + { + qDebug() << "Error failed to spawn"; + return 1; + } + qDebug() << "Launched"; + } + return a.exec(); + } + QProcess process; + QStringList args; + args << "ipc"; + if(!process.startDetached("/proc/self/exe", args)) + { + QString errorMsg = "Failed to start IPC server"; + qDebug() << errorMsg; + QMessageBox::critical(nullptr, "Error", errorMsg); + } + struct qssb_policy *policy = qssb_init_policy(); std::string appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString(); - + std::string sockPath = socketPath.toStdString(); policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER; + qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE, "/"); qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE, appDataLocation.c_str()); @@ -44,7 +76,9 @@ int main(int argc, char *argv[]) qRegisterMetaType>("QVector"); qRegisterMetaType>("QVector"); qRegisterMetaType("PdfPreview"); - MainWindow w; + + IPCClient client{socketPath}; + MainWindow w{0, client}; w.showMaximized(); return a.exec(); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 9f1487f..7049457 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -18,10 +18,11 @@ #include "../shared/looqsgeneralexception.h" #include "../shared/common.h" -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) +MainWindow::MainWindow(QWidget *parent, IPCClient &client) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setWindowTitle(QCoreApplication::applicationName()); + this->ipcClient = &client; QSettings settings; db = QSqlDatabase::addDatabase("QSQLITE"); @@ -136,29 +137,7 @@ void MainWindow::pdfPreviewReceived(PdfPreview preview) label->setPixmap(QPixmap::fromImage(preview.previewImage)); label->setToolTip(preview.documentPath); ui->scrollAreaWidgetContents->layout()->addWidget(label); - connect(label, &ClickLabel::leftClick, - [docPath, previewPage]() - { - QSettings settings; - QString command = settings.value("pdfviewer").toString(); - if(command != "" && command.contains("%p") && command.contains("%f")) - { - QStringList splitted = command.split(" "); - if(splitted.size() > 1) - { - QString cmd = splitted[0]; - QStringList args = splitted.mid(1); - args.replaceInStrings("%f", docPath); - args.replaceInStrings("%p", QString::number(previewPage)); - - QProcess::startDetached(cmd, args); - } - } - else - { - QDesktopServices::openUrl(QUrl::fromLocalFile(docPath)); - } - }); + connect(label, &ClickLabel::leftClick, [this, docPath, previewPage]() { ipcDocOpen(docPath, previewPage); }); connect(label, &ClickLabel::rightClick, [this, docPath, previewPage]() { @@ -301,17 +280,27 @@ void MainWindow::createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo) [&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.fileName()); }); menu.addAction("Copy full path to clipboard", [&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.absoluteFilePath()); }); - menu.addAction("Open containing folder", - [&fileInfo] - { - QString dir = fileInfo.absolutePath(); - QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); - }); + menu.addAction("Open containing folder", [this, &fileInfo] { this->ipcFileOpen(fileInfo.absolutePath()); }); +} + +void MainWindow::ipcDocOpen(QString path, int num) +{ + QStringList args; + args << path; + args << QString::number(num); + this->ipcClient->sendCommand(DocOpen, args); +} + +void MainWindow::ipcFileOpen(QString path) +{ + QStringList args; + args << path; + this->ipcClient->sendCommand(FileOpen, args); } void MainWindow::treeSearchItemActivated(QTreeWidgetItem *item, int i) { - QDesktopServices::openUrl(QUrl::fromLocalFile(item->text(1))); + ipcFileOpen(item->text(1)); } void MainWindow::showSearchResultsContextMenu(const QPoint &point) diff --git a/gui/mainwindow.h b/gui/mainwindow.h index f6a3dd0..40eb12f 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -8,8 +8,10 @@ #include #include #include +#include #include "pdfworker.h" #include "../shared/looqsquery.h" +#include "ipcclient.h" namespace Ui { class MainWindow; @@ -20,7 +22,7 @@ class MainWindow : public QMainWindow Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent, IPCClient &client); ~MainWindow(); signals: void beginSearch(const QString &query); @@ -28,6 +30,7 @@ class MainWindow : public QMainWindow private: Ui::MainWindow *ui; + IPCClient *ipcClient; QFileIconProvider iconProvider; bool pdfDirty; QSqlDatabase db; @@ -45,6 +48,9 @@ class MainWindow : public QMainWindow LooqsQuery currentQuery; int pdfPreviewsPerPage; void createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo); + void ipcDocOpen(QString path, int num); + void ipcFileOpen(QString path); + private slots: void lineEditReturnPressed(); void treeSearchItemActivated(QTreeWidgetItem *item, int i); diff --git a/shared/shared.pro b/shared/shared.pro index 88072ea..1e943ee 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -13,6 +13,8 @@ TEMPLATE = lib CONFIG += staticlib CONFIG += c++17 +INCLUDEPATH += $$PWD/../sandbox/qssb.h/ + # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the diff --git a/submodules/qssb.h b/submodules/qssb.h index 75f607b..692c9b5 160000 --- a/submodules/qssb.h +++ b/submodules/qssb.h @@ -1 +1 @@ -Subproject commit 75f607bc350354ed31fd0977311917e13241e703 +Subproject commit 692c9b54b7b5fdca6a416d91d3f34d15af185c33 -- 2.47.1 From b1f3e956229047da2f96fe560b58c7532e0f3357 Mon Sep 17 00:00:00 2001 From: Albert S Date: Mon, 25 Oct 2021 17:18:11 +0200 Subject: [PATCH 07/13] shared: looksquery: Fix incorrect varname in exception --- shared/looqsquery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/looqsquery.cpp b/shared/looqsquery.cpp index fdcded7..15b53ae 100644 --- a/shared/looqsquery.cpp +++ b/shared/looqsquery.cpp @@ -128,7 +128,7 @@ QVector createSortConditions(QString sortExpression) } else { - throw LooqsGeneralException("Unknown order specifier: " + order); + throw LooqsGeneralException("Unknown order specifier: " + orderstr); } } else -- 2.47.1 From 88ee2383f7c30c2883dbb9b90fa1553e97e7658d Mon Sep 17 00:00:00 2001 From: Albert S Date: Sun, 26 Dec 2021 18:21:48 +0100 Subject: [PATCH 08/13] Switch to exile.h --- .gitmodules | 6 +++--- cli/sandboxedprocessor.cpp | 12 ++++++------ gui/main.cpp | 18 ++++++++---------- shared/shared.pro | 2 +- submodules/exile.h | 1 + submodules/qssb.h | 1 - 6 files changed, 19 insertions(+), 21 deletions(-) create mode 160000 submodules/exile.h delete mode 160000 submodules/qssb.h diff --git a/.gitmodules b/.gitmodules index ba48fd5..3ed67ad 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "submodules/qssb.h"] - path = submodules/qssb.h - url = https://gitea.quitesimple.org/crtxcr/qssb.h +[submodule "submodules/exile.h"] + path = submodules/exile.h + url = https://gitea.quitesimple.org/crtxcr/exile.h diff --git a/cli/sandboxedprocessor.cpp b/cli/sandboxedprocessor.cpp index 3341c57..3f722d9 100644 --- a/cli/sandboxedprocessor.cpp +++ b/cli/sandboxedprocessor.cpp @@ -8,7 +8,7 @@ #include "nothingprocessor.h" #include "odtprocessor.h" #include "odsprocessor.h" -#include "../submodules/qssb.h/qssb.h" +#include "../submodules/exile.h/exile.h" #include "logger.h" static DefaultTextProcessor *defaultTextProcessor = new DefaultTextProcessor(); @@ -26,26 +26,26 @@ static QMap processors{ void SandboxedProcessor::enableSandbox(QString readablePath) { - struct qssb_policy *policy = qssb_init_policy(); + struct exile_policy *policy = exile_init_policy(); - policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER; + policy->namespace_options = EXILE_UNSHARE_NETWORK | EXILE_UNSHARE_USER; if(!readablePath.isEmpty()) { std::string readablePathLocation = readablePath.toStdString(); - qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ, readablePathLocation.c_str()); + exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ, readablePathLocation.c_str()); } else { policy->no_fs = 1; } - int ret = qssb_enable_policy(policy); + int ret = exile_enable_policy(policy); if(ret != 0) { qDebug() << "Failed to establish sandbox: " << ret; exit(EXIT_FAILURE); } - qssb_free_policy(policy); + exile_free_policy(policy); } void SandboxedProcessor::printResults(const QVector &pageData) diff --git a/gui/main.cpp b/gui/main.cpp index 06dcfeb..02819c6 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -8,7 +8,7 @@ #include "searchresult.h" #include "pdfpreview.h" #include "../shared/common.h" -#include "../submodules/qssb.h/qssb.h" +#include "../submodules/exile.h/exile.h" #include "ipcserver.h" int main(int argc, char *argv[]) @@ -41,25 +41,23 @@ int main(int argc, char *argv[]) QMessageBox::critical(nullptr, "Error", errorMsg); } - struct qssb_policy *policy = qssb_init_policy(); + struct exile_policy *policy = exile_init_policy(); std::string appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString(); std::string sockPath = socketPath.toStdString(); - policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER; + policy->namespace_options = EXILE_UNSHARE_NETWORK | EXILE_UNSHARE_USER; - qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE, "/"); - qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE, - appDataLocation.c_str()); - qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE, - cacheDataLocation.c_str()); + exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_REMOVE_FILE, "/"); + exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, appDataLocation.c_str()); + exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, cacheDataLocation.c_str()); - int ret = qssb_enable_policy(policy); + int ret = exile_enable_policy(policy); if(ret != 0) { qDebug() << "Failed to establish sandbox"; return 1; } - qssb_free_policy(policy); + exile_free_policy(policy); Common::setupAppInfo(); QApplication a(argc, argv); diff --git a/shared/shared.pro b/shared/shared.pro index 1e943ee..fbbdd8b 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -13,7 +13,7 @@ TEMPLATE = lib CONFIG += staticlib CONFIG += c++17 -INCLUDEPATH += $$PWD/../sandbox/qssb.h/ +INCLUDEPATH += $$PWD/../sandbox/exile.h/ # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings diff --git a/submodules/exile.h b/submodules/exile.h new file mode 160000 index 0000000..d742397 --- /dev/null +++ b/submodules/exile.h @@ -0,0 +1 @@ +Subproject commit d742397b522eb91513bab54a3aa992dfb7121462 diff --git a/submodules/qssb.h b/submodules/qssb.h deleted file mode 160000 index 692c9b5..0000000 --- a/submodules/qssb.h +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 692c9b54b7b5fdca6a416d91d3f34d15af185c33 -- 2.47.1 From ba636bf0fc2bbf894492d01aa328272b97a71f1a Mon Sep 17 00:00:00 2001 From: Albert S Date: Sun, 26 Dec 2021 18:35:55 +0100 Subject: [PATCH 09/13] IpcServer: Fix off-by-one --- gui/ipcserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/ipcserver.cpp b/gui/ipcserver.cpp index 01ec349..d7d8dc5 100644 --- a/gui/ipcserver.cpp +++ b/gui/ipcserver.cpp @@ -73,7 +73,7 @@ void IpcServer::spawnerNewConnection() stream << "invalid"; return; } - docOpen(args[0], args[2].toInt()); + docOpen(args[0], args[1].toInt()); } if(command == FileOpen) { -- 2.47.1 From f0260ee14a4e12b1eddaf7eb60c8e1713e6310e0 Mon Sep 17 00:00:00 2001 From: Albert S Date: Wed, 29 Dec 2021 11:51:52 +0100 Subject: [PATCH 10/13] gui: Add vow_promises to exile policy --- gui/main.cpp | 5 ++++- submodules/exile.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gui/main.cpp b/gui/main.cpp index 02819c6..aeb91eb 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -46,7 +46,10 @@ int main(int argc, char *argv[]) std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString(); std::string sockPath = socketPath.toStdString(); policy->namespace_options = EXILE_UNSHARE_NETWORK | EXILE_UNSHARE_USER; - + policy->vow_promises = EXILE_SYSCALL_VOW_THREAD | EXILE_SYSCALL_VOW_CPATH | EXILE_SYSCALL_VOW_WPATH | + EXILE_SYSCALL_VOW_RPATH | EXILE_SYSCALL_VOW_UNIX | EXILE_SYSCALL_VOW_STDIO | + EXILE_SYSCALL_VOW_PROT_EXEC | EXILE_SYSCALL_VOW_PROC | EXILE_SYSCALL_VOW_SHM | + EXILE_SYSCALL_VOW_FSNOTIFY | EXILE_SYSCALL_VOW_IOCTL; exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_REMOVE_FILE, "/"); exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, appDataLocation.c_str()); exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, cacheDataLocation.c_str()); diff --git a/submodules/exile.h b/submodules/exile.h index d742397..4824c6e 160000 --- a/submodules/exile.h +++ b/submodules/exile.h @@ -1 +1 @@ -Subproject commit d742397b522eb91513bab54a3aa992dfb7121462 +Subproject commit 4824c6eaa9043878daaba7b3778338f5bf913f06 -- 2.47.1 From 42b49fa43e6b57c288bb68284023bbe5f9cc9097 Mon Sep 17 00:00:00 2001 From: Albert S Date: Thu, 30 Dec 2021 12:17:12 +0100 Subject: [PATCH 11/13] gui: Perform content search and path search by default Search for content and paths. Merge lone words for content search. This behaviour is much more natural than typing "c:()". --- cli/commandlist.cpp | 2 +- cli/commandsearch.cpp | 2 +- gui/mainwindow.cpp | 11 ++++++++--- gui/mainwindow.h | 2 +- shared/looqsquery.cpp | 18 +++++++++++++++--- shared/looqsquery.h | 2 +- 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/cli/commandlist.cpp b/cli/commandlist.cpp index 31e0ff6..fa1fbd2 100644 --- a/cli/commandlist.cpp +++ b/cli/commandlist.cpp @@ -24,7 +24,7 @@ int CommandList::handle(QStringList arguments) QStringList files = parser.positionalArguments(); QString queryStrings = files.join(' '); - auto results = dbService->search(LooqsQuery::build(queryStrings)); + auto results = dbService->search(LooqsQuery::build(queryStrings, TokenType::FILTER_PATH_CONTAINS, false)); for(SearchResult &result : results) { diff --git a/cli/commandsearch.cpp b/cli/commandsearch.cpp index 4350171..e7ed114 100644 --- a/cli/commandsearch.cpp +++ b/cli/commandsearch.cpp @@ -16,7 +16,7 @@ int CommandSearch::handle(QStringList arguments) QStringList files = parser.positionalArguments(); QString queryStrings = files.join(' '); - LooqsQuery query = LooqsQuery::build(queryStrings); + LooqsQuery query = LooqsQuery::build(queryStrings, TokenType::FILTER_PATH_CONTAINS, false); bool reverse = parser.isSet("reverse"); if(reverse) { diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 7049457..c55cbd4 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -166,8 +166,13 @@ void MainWindow::lineEditReturnPressed() [&, q]() { SqliteSearch searcher(db); - this->currentQuery = LooqsQuery::build(q); - return searcher.search(this->currentQuery); + this->contentSearchQuery = LooqsQuery::build(q, TokenType::FILTER_CONTENT_CONTAINS, true); + + LooqsQuery filesQuery = LooqsQuery::build(q, TokenType::FILTER_PATH_CONTAINS, false); + QVector results; + results.append(searcher.search(filesQuery)); + results.append(searcher.search(this->contentSearchQuery)); + return results; }); searchWatcher.setFuture(searchFuture); } @@ -243,7 +248,7 @@ void MainWindow::makePdfPreview(int page) QVector wordsToHighlight; QRegularExpression extractor(R"#("([^"]*)"|(\w+))#"); - for(const Token &token : this->currentQuery.getTokens()) + for(const Token &token : this->contentSearchQuery.getTokens()) { if(token.type == FILTER_CONTENT_CONTAINS) { diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 40eb12f..053274d 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -45,7 +45,7 @@ class MainWindow : public QMainWindow unsigned int processedPdfPreviews; void handleSearchResults(const QVector &results); void handleSearchError(QString error); - LooqsQuery currentQuery; + LooqsQuery contentSearchQuery; int pdfPreviewsPerPage; void createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo); void ipcDocOpen(QString path, int num); diff --git a/shared/looqsquery.cpp b/shared/looqsquery.cpp index 15b53ae..6cb4567 100644 --- a/shared/looqsquery.cpp +++ b/shared/looqsquery.cpp @@ -157,15 +157,15 @@ void LooqsQuery::addToken(Token t) * thus, "Downloads zip" becomes essentailly "path.contains:(Downloads) AND path.contains:(zip)" * * TODO: It's a bit ugly still*/ -LooqsQuery LooqsQuery::build(QString expression) +LooqsQuery LooqsQuery::build(QString expression, TokenType loneWordsTokenType, bool mergeLoneWords) { if(!checkParanthesis(expression)) { throw LooqsGeneralException("Invalid paranthesis"); } + QStringList loneWords; LooqsQuery result; - // TODO: merge lonewords QRegularExpression rx("((?(\\.|\\w)+):(?\\((?[^\\)]+)\\)|([\\w,])+)|(?AND|OR)" "|(?!)|(?\\(|\\))|(?\\w+))"); QRegularExpressionMatchIterator i = rx.globalMatch(expression); @@ -233,7 +233,14 @@ LooqsQuery LooqsQuery::build(QString expression) if(loneword != "") { - result.addToken(Token(FILTER_PATH_CONTAINS, loneword)); + if(mergeLoneWords) + { + loneWords.append(loneword); + } + else + { + result.addToken(Token(loneWordsTokenType, loneword)); + } } if(filtername != "") @@ -292,6 +299,11 @@ LooqsQuery LooqsQuery::build(QString expression) } } + if(mergeLoneWords) + { + result.addToken(Token(loneWordsTokenType, loneWords.join(' '))); + } + bool contentsearch = (result.getTokensMask() & FILTER_CONTENT) == FILTER_CONTENT; bool sortsForContent = std::any_of(result.sortConditions.begin(), result.sortConditions.end(), [](SortCondition c) { return c.field == CONTENT_TEXT; }); diff --git a/shared/looqsquery.h b/shared/looqsquery.h index da6c9c7..c0a0e76 100644 --- a/shared/looqsquery.h +++ b/shared/looqsquery.h @@ -54,7 +54,7 @@ class LooqsQuery } void addSortCondition(SortCondition sc); static bool checkParanthesis(QString query); - static LooqsQuery build(QString query); + static LooqsQuery build(QString query, TokenType loneWordsTokenType, bool mergeLoneWords); }; #endif // LOOQSQUERY_H -- 2.47.1 From 99f35beb4a1304530310e17beeae053d80e6fc25 Mon Sep 17 00:00:00 2001 From: Albert S Date: Thu, 30 Dec 2021 12:31:32 +0100 Subject: [PATCH 12/13] gui: Call setupAppinfo() also for the IPC server --- gui/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/main.cpp b/gui/main.cpp index aeb91eb..2e34bea 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -16,6 +16,7 @@ int main(int argc, char *argv[]) QString socketPath = "/tmp/looqs-spawner"; if(argc > 1) { + Common::setupAppInfo(); QApplication a(argc, argv); QString arg = argv[1]; if(arg == "ipc") -- 2.47.1 From ec798658451b4a1775fb331337f2cfc5d021a8be Mon Sep 17 00:00:00 2001 From: Albert S Date: Sun, 2 Jan 2022 16:15:55 +0100 Subject: [PATCH 13/13] fixup! gui: Add vow_promises to exile policy --- gui/main.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/gui/main.cpp b/gui/main.cpp index 2e34bea..9449d18 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) qDebug() << "Launching ipc"; if(!ipcserver->startSpawner(socketPath)) { - qDebug() << "Error failed to spawn"; + qCritical() << "Error failed to spawn"; return 1; } qDebug() << "Launched"; @@ -43,6 +43,11 @@ int main(int argc, char *argv[]) } struct exile_policy *policy = exile_init_policy(); + if(policy == NULL) + { + qCritical() << "Failed to init policy for sandbox"; + return 1; + } std::string appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString(); std::string sockPath = socketPath.toStdString(); @@ -51,10 +56,25 @@ int main(int argc, char *argv[]) EXILE_SYSCALL_VOW_RPATH | EXILE_SYSCALL_VOW_UNIX | EXILE_SYSCALL_VOW_STDIO | EXILE_SYSCALL_VOW_PROT_EXEC | EXILE_SYSCALL_VOW_PROC | EXILE_SYSCALL_VOW_SHM | EXILE_SYSCALL_VOW_FSNOTIFY | EXILE_SYSCALL_VOW_IOCTL; - exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_REMOVE_FILE, "/"); - exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, appDataLocation.c_str()); - exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, cacheDataLocation.c_str()); + if(exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_REMOVE_FILE, "/") != 0) + { + qCritical() << "Failed to append a path to the path policy"; + return 1; + } + + if(exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, appDataLocation.c_str()) != + 0) + { + qCritical() << "Failed to append a path to the path policy"; + return 1; + } + if(exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, + cacheDataLocation.c_str()) != 0) + { + qCritical() << "Failed to append a path to the path policy"; + return 1; + } int ret = exile_enable_policy(policy); if(ret != 0) { -- 2.47.1