You've already forked isolationRunner
New feature; add encrypt-at-rest
When a jail is encryted at rest using 'encfs' we detect that and ask for a password upon starting the jail. This sounded like a neat little idea which ended up taking nearly 4 days to do... EncFS needs to be running as root, as it is a FUSE system and it will actually stop root from reading/writing files if it is running as a user. It also is very picky about not running in a namespace, it manages to hang indefinitely otherwise where a shutdown can't complete because the process doesn't want to die :-) So, it runs as root, takes the password via a pipe and we have a watchdog proces to kill it when the jail is shut down.
This commit is contained in:
+2
-2
@@ -5,7 +5,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
find_package(Qt6 COMPONENTS Core DBus REQUIRED)
|
find_package(Qt6 COMPONENTS Core Widgets DBus REQUIRED)
|
||||||
|
|
||||||
# starting with Qt5.15 we have a lot of deprecation warnings,
|
# starting with Qt5.15 we have a lot of deprecation warnings,
|
||||||
# likely to make porting to Qt6 easier.
|
# likely to make porting to Qt6 easier.
|
||||||
@@ -24,7 +24,7 @@ set (SERVER_SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(isolation_runner ${SERVER_SOURCES})
|
add_executable(isolation_runner ${SERVER_SOURCES})
|
||||||
target_link_libraries(isolation_runner Qt6::Core Qt6::DBus)
|
target_link_libraries(isolation_runner Qt6::Core Qt6::DBus Qt6::Widgets)
|
||||||
|
|
||||||
if ("$ENV{HOME}" STREQUAL "/root") # hacky way to know if we're root.
|
if ("$ENV{HOME}" STREQUAL "/root") # hacky way to know if we're root.
|
||||||
# setuid is needed, we can apply that when root installs it.
|
# setuid is needed, we can apply that when root installs it.
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
class RulesError : public std::runtime_error
|
class RulesError : public std::runtime_error
|
||||||
{
|
{
|
||||||
@@ -67,10 +68,20 @@ QString IsolationManager::startApplicationRequest(AppEntry &dbEntry, const QStri
|
|||||||
if (!base.mkpath(homedir))
|
if (!base.mkpath(homedir))
|
||||||
return QString("Internal error: failed to create environment");
|
return QString("Internal error: failed to create environment");
|
||||||
|
|
||||||
|
if (dbEntry.jailPassword.isEmpty()
|
||||||
|
&& QFile::exists(m_basedir % "/." % homedir % "/.encfs6.xml")) {
|
||||||
|
auto *da = new DelayedApp(dbEntry, arguments, this);
|
||||||
|
da->askPassword();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
// then ask the priviledged task to take it from here.
|
// then ask the priviledged task to take it from here.
|
||||||
Message message(Message::MAX_SIZE);
|
Message message(Message::MAX_SIZE);
|
||||||
message.setJailId(dbEntry.appId);
|
message.setJailId(dbEntry.appId);
|
||||||
try {
|
try {
|
||||||
|
if (!dbEntry.jailPassword.isEmpty())
|
||||||
|
message.setJailPassword(dbEntry.jailPassword.toStdString());
|
||||||
|
|
||||||
QString exe = dbEntry.pathToExe;
|
QString exe = dbEntry.pathToExe;
|
||||||
// resolve symlinks and actually find the real executable.
|
// resolve symlinks and actually find the real executable.
|
||||||
for (int i = 0; i < 10; ++i) { // avoid endless loops
|
for (int i = 0; i < 10; ++i) { // avoid endless loops
|
||||||
@@ -515,3 +526,38 @@ void AutoDeleter::jailClosed(const QString &pipeFile)
|
|||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DelayedApp::DelayedApp(IsolationManager::AppEntry appEntry, const QStringList &arguments, IsolationManager *parent)
|
||||||
|
: m_jail(appEntry),
|
||||||
|
m_parent(parent),
|
||||||
|
m_arguments(arguments)
|
||||||
|
{
|
||||||
|
assert(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedApp::askPassword()
|
||||||
|
{
|
||||||
|
auto id = new QInputDialog();
|
||||||
|
m_win = id;
|
||||||
|
id->setInputMode(QInputDialog::TextInput);
|
||||||
|
id->setTextEchoMode(QLineEdit::Password);
|
||||||
|
id->setLabelText("ISO password:");
|
||||||
|
id->setWindowTitle("Jail Requires Password");
|
||||||
|
id->open(this, SLOT(passwordEntered(QString)));
|
||||||
|
connect (id, SIGNAL(rejected()), this, SLOT(cancelPressed()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedApp::cancelPressed()
|
||||||
|
{
|
||||||
|
qWarning() << "canceled";
|
||||||
|
m_win->deleteLater();
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedApp::passwordEntered(const QString &text)
|
||||||
|
{
|
||||||
|
m_win->deleteLater();
|
||||||
|
m_jail.jailPassword = text;
|
||||||
|
m_parent->startApplicationRequest(m_jail, m_arguments);
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
|
|
||||||
|
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The isolation-manager is the biggest part of the
|
* The isolation-manager is the biggest part of the
|
||||||
* server. It is the listener and it drops root priviledges
|
* server. It is the listener and it drops root priviledges
|
||||||
@@ -32,6 +35,7 @@ public:
|
|||||||
QStringList denied;
|
QStringList denied;
|
||||||
QStringList allowed;
|
QStringList allowed;
|
||||||
QString initScript;
|
QString initScript;
|
||||||
|
QString jailPassword;
|
||||||
bool autoDelete = false;
|
bool autoDelete = false;
|
||||||
|
|
||||||
// defaults as read from the rules file
|
// defaults as read from the rules file
|
||||||
@@ -107,4 +111,24 @@ private:
|
|||||||
QFileSystemWatcher m_watcher;
|
QFileSystemWatcher m_watcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DelayedApp : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DelayedApp(IsolationManager::AppEntry appEntry, const QStringList &arguments, IsolationManager *parent);
|
||||||
|
|
||||||
|
void askPassword();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void cancelPressed();
|
||||||
|
void passwordEntered(const QString &text);
|
||||||
|
|
||||||
|
private:
|
||||||
|
IsolationManager *m_parent;
|
||||||
|
IsolationManager::AppEntry m_jail;
|
||||||
|
const QStringList m_arguments;
|
||||||
|
|
||||||
|
QWidget *m_win = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+13
@@ -11,6 +11,7 @@ enum FieldType {
|
|||||||
ExecutablePath = 10,
|
ExecutablePath = 10,
|
||||||
Argument,
|
Argument,
|
||||||
InitScript,
|
InitScript,
|
||||||
|
JailPassword, // The jaildir is encfs encrypted. Decrypt password.
|
||||||
|
|
||||||
IsTry = 20, // allow next command to fail
|
IsTry = 20, // allow next command to fail
|
||||||
RBindMountSource, // mount from an existing directory.
|
RBindMountSource, // mount from an existing directory.
|
||||||
@@ -247,6 +248,11 @@ void Message::addEnvToSet(const std::string &envVar)
|
|||||||
addString(EnvironSet, envVar);
|
addString(EnvironSet, envVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Message::setJailPassword(const std::string &pwd)
|
||||||
|
{
|
||||||
|
addString(JailPassword, pwd);
|
||||||
|
}
|
||||||
|
|
||||||
void Message::addDBusProxy(DBusType type, const std::string &from, const std::string &to)
|
void Message::addDBusProxy(DBusType type, const std::string &from, const std::string &to)
|
||||||
{
|
{
|
||||||
addString(type == UserSessionBus ? DBusProxyFrom : DBusProxySystemFrom, from);
|
addString(type == UserSessionBus ? DBusProxyFrom : DBusProxySystemFrom, from);
|
||||||
@@ -342,6 +348,12 @@ bool Message::Iterator::isInitSript() const
|
|||||||
return m_cur[0] == InitScript;
|
return m_cur[0] == InitScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Message::Iterator::isJailPwd() const
|
||||||
|
{
|
||||||
|
assert(isValid());
|
||||||
|
return m_cur[0] == JailPassword;
|
||||||
|
}
|
||||||
|
|
||||||
bool Message::Iterator::isValid() const
|
bool Message::Iterator::isValid() const
|
||||||
{
|
{
|
||||||
assert(m_parent);
|
assert(m_parent);
|
||||||
@@ -494,6 +506,7 @@ bool Message::Iterator::next()
|
|||||||
case EnvironSet: // fall through
|
case EnvironSet: // fall through
|
||||||
case EnvironUnset: // fall through
|
case EnvironUnset: // fall through
|
||||||
case InitScript: // fall through
|
case InitScript: // fall through
|
||||||
|
case JailPassword: // fall through
|
||||||
case CreateTmpFs:
|
case CreateTmpFs:
|
||||||
m_recordSize = ::stringLength(m_cur + 1, end) + 2;
|
m_recordSize = ::stringLength(m_cur + 1, end) + 2;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ public:
|
|||||||
|
|
||||||
void addEnvToUnset(const std::string &propertyName);
|
void addEnvToUnset(const std::string &propertyName);
|
||||||
void addEnvToSet(const std::string &envVar);
|
void addEnvToSet(const std::string &envVar);
|
||||||
|
void setJailPassword(const std::string &pwd);
|
||||||
|
|
||||||
enum DBusType {
|
enum DBusType {
|
||||||
UserSessionBus,
|
UserSessionBus,
|
||||||
@@ -99,6 +100,7 @@ public:
|
|||||||
bool isCopy() const;
|
bool isCopy() const;
|
||||||
bool isJailId() const;
|
bool isJailId() const;
|
||||||
bool isInitSript() const;
|
bool isInitSript() const;
|
||||||
|
bool isJailPwd() const;
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool isTry() const {
|
bool isTry() const {
|
||||||
return m_isTry;
|
return m_isTry;
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ RemoteRunner::~RemoteRunner()
|
|||||||
m_thread.wait();
|
m_thread.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRunner::runRemote(const Message &message)
|
void RemoteRunner::runRemote(const Message &message) const
|
||||||
{
|
{
|
||||||
assert(message.size() > 0);
|
assert(message.size() > 0);
|
||||||
assert(message.size() < 0x7FFF);
|
assert(message.size() < 0x7FFF);
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ public:
|
|||||||
RemoteRunner(int inputId, int outputId);
|
RemoteRunner(int inputId, int outputId);
|
||||||
~RemoteRunner();
|
~RemoteRunner();
|
||||||
|
|
||||||
void runRemote(const Message &message);
|
void runRemote(const Message &message) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void receivedMessage(QByteArray data);
|
void receivedMessage(QByteArray data);
|
||||||
|
|||||||
+170
-11
@@ -13,10 +13,14 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
#define PIPE_READ 0
|
||||||
|
#define PIPE_WRITE 1
|
||||||
|
|
||||||
// the waiting thread.
|
// the waiting thread.
|
||||||
void waitForChildren(pid_t pid)
|
void waitForChildren(pid_t pid, const int encFsWatchDogPipe)
|
||||||
{
|
{
|
||||||
static std::atomic_int childCount(0);
|
static std::atomic_int childCount(0);
|
||||||
childCount.fetch_add(1);
|
childCount.fetch_add(1);
|
||||||
@@ -37,14 +41,32 @@ void waitForChildren(pid_t pid)
|
|||||||
// realistically, the next line is irrelevant since nobody is listening.
|
// realistically, the next line is irrelevant since nobody is listening.
|
||||||
fprintf(stderr, "failed to remove iso-pipe. Error: %s\n", e.what());
|
fprintf(stderr, "failed to remove iso-pipe. Error: %s\n", e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (encFsWatchDogPipe)
|
||||||
|
write(encFsWatchDogPipe, "go!", 3); // the watchdog sends the kill signal to the encFS process.
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waitForEncFs(pid_t pid)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
// if the watched encfs process dies, typically because of an
|
||||||
|
// incorrect password, the starting of the jail should be cancelled.
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
Runner::Runner(const Message &message, int errorFile)
|
Runner::Runner(const Message &message, int errorFile)
|
||||||
: m_outputFD(errorFile),
|
: m_outputFD(errorFile),
|
||||||
m_message(message)
|
m_message(message)
|
||||||
{
|
{
|
||||||
|
for (auto i = m_message.iBegin(); i.isValid(); i.next()) {
|
||||||
|
if (i.isJailId()) {
|
||||||
|
m_jailId = i.jailId();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runner::setOwnerUserId(uint32_t uid)
|
void Runner::setOwnerUserId(uint32_t uid)
|
||||||
@@ -80,6 +102,23 @@ void Runner::run()
|
|||||||
close(fd); // cleanup
|
close(fd); // cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* While still fully root, start the encfs base, if needed.
|
||||||
|
*/
|
||||||
|
int encFSWatchDog = 0;
|
||||||
|
for (auto i = m_message.iBegin(); i.isValid(); i.next()) {
|
||||||
|
if (i.isJailPwd()) {
|
||||||
|
// we decrypt the jail with the password given.
|
||||||
|
encFSWatchDog = runEncFs(i.stringPtr(), i.stringLength());
|
||||||
|
if (encFSWatchDog == 0) {
|
||||||
|
fprintf(stderr, "Failed to run encfs\n");
|
||||||
|
exit(18);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'unshare' is the nicest way to run a program in a new namespace.
|
* 'unshare' is the nicest way to run a program in a new namespace.
|
||||||
* PID 'unshare' means that the to-be-run application can not see which other
|
* PID 'unshare' means that the to-be-run application can not see which other
|
||||||
@@ -321,7 +360,7 @@ void Runner::run()
|
|||||||
if (pid) { // parent
|
if (pid) { // parent
|
||||||
// printf("Fork 3 done, created %d (I'm %d). waiting for child to exit\n", pid, getpid());
|
// printf("Fork 3 done, created %d (I'm %d). waiting for child to exit\n", pid, getpid());
|
||||||
renameThisProcess(m_processName, m_processNameSize, "jailer");
|
renameThisProcess(m_processName, m_processNameSize, "jailer");
|
||||||
new std::thread(waitForChildren, pid);
|
new std::thread(waitForChildren, pid, encFSWatchDog);
|
||||||
|
|
||||||
// create the pipe that indicates this jail is occupied.
|
// create the pipe that indicates this jail is occupied.
|
||||||
// the pipe can be used by the dispatcher to send us more things to run
|
// the pipe can be used by the dispatcher to send us more things to run
|
||||||
@@ -360,7 +399,7 @@ void Runner::run()
|
|||||||
if (pid == -1) exit(1);
|
if (pid == -1) exit(1);
|
||||||
if (pid) { // I'm parent
|
if (pid) { // I'm parent
|
||||||
// pid is child's pid, lets wait for them in a thread.
|
// pid is child's pid, lets wait for them in a thread.
|
||||||
new std::thread(waitForChildren, pid);
|
new std::thread(waitForChildren, pid, encFSWatchDog);
|
||||||
}
|
}
|
||||||
else { // run up to exec, below!
|
else { // run up to exec, below!
|
||||||
m_message = Message(buf, msgSize);
|
m_message = Message(buf, msgSize);
|
||||||
@@ -405,15 +444,8 @@ void Runner::run()
|
|||||||
void Runner::sendUpstream(const char *errorMessage)
|
void Runner::sendUpstream(const char *errorMessage)
|
||||||
{
|
{
|
||||||
assert(errorMessage);
|
assert(errorMessage);
|
||||||
uint32_t jailId = 0;
|
|
||||||
for (auto i = m_message.iBegin(); i.isValid(); i.next()) {
|
|
||||||
if (i.isJailId()) {
|
|
||||||
jailId = i.jailId();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char messageBuf[20];
|
char messageBuf[20];
|
||||||
int size = snprintf(messageBuf, sizeof(messageBuf) - 1, "%u ", jailId);
|
int size = snprintf(messageBuf, sizeof(messageBuf) - 1, "%u ", m_jailId);
|
||||||
write(m_outputFD, messageBuf, size);
|
write(m_outputFD, messageBuf, size);
|
||||||
const int len = strlen(errorMessage);
|
const int len = strlen(errorMessage);
|
||||||
write(m_outputFD, errorMessage, len + 1); // including trailing zero
|
write(m_outputFD, errorMessage, len + 1); // including trailing zero
|
||||||
@@ -588,6 +620,133 @@ int Runner::runInitScript()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Runner::runEncFs(const char *password, int strlen) const
|
||||||
|
{
|
||||||
|
int aStdinPipe[2];
|
||||||
|
if (pipe(aStdinPipe) < 0) {
|
||||||
|
perror("allocating pipe for encfs");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
fprintf(stderr, "Runner: Failed to fork\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char buf[20];
|
||||||
|
snprintf(buf, sizeof(buf), "%d", m_jailId);
|
||||||
|
const std::string jailName(buf);
|
||||||
|
char *curDir = getcwd(nullptr, 0);
|
||||||
|
const std::string curDirStr(curDir);
|
||||||
|
free(curDir);
|
||||||
|
std::string jaildir = curDirStr + "/" + jailName;
|
||||||
|
|
||||||
|
if (pid == 0) { // we are the child
|
||||||
|
// redirect stdin to our pipe
|
||||||
|
if (dup2(aStdinPipe[PIPE_READ], STDIN_FILENO) == -1) {
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are for use by parent only
|
||||||
|
close(aStdinPipe[PIPE_READ]);
|
||||||
|
close(aStdinPipe[PIPE_WRITE]);
|
||||||
|
// close(aStdoutPipe[PIPE_READ]);
|
||||||
|
// close(aStdoutPipe[PIPE_WRITE]);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
|
||||||
|
char *arguments[7];
|
||||||
|
arguments[0] = const_cast<char*>("/usr/bin/encfs");
|
||||||
|
arguments[1] = const_cast<char*>("-f"); // foreground. Don't fork.
|
||||||
|
arguments[2] = const_cast<char*>("--public");
|
||||||
|
arguments[3] = const_cast<char*>("--stdinpass");
|
||||||
|
std::string backend = curDirStr + "/." + jailName;
|
||||||
|
arguments[4] = const_cast<char*>(backend.c_str());
|
||||||
|
arguments[5] = const_cast<char*>(jaildir.c_str());
|
||||||
|
arguments[6] = 0;
|
||||||
|
|
||||||
|
execv(arguments[0], arguments);
|
||||||
|
}
|
||||||
|
else {// we are the parent (pid = child's pid)
|
||||||
|
close(aStdinPipe[PIPE_READ]);
|
||||||
|
|
||||||
|
// monitor the process, if it dies we should die too.
|
||||||
|
new std::thread(waitForEncFs, pid);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
// next we wait for the target dir to actually become a mount.
|
||||||
|
dev_t oldDevice = 0;
|
||||||
|
for (int i = 0; i < 200; ++i) { // max 15 sec
|
||||||
|
struct stat targetDir;
|
||||||
|
if (stat(jaildir.c_str(), &targetDir)) {
|
||||||
|
printf("stat of encrypted dir failed '%s'\n", jaildir.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
// On first loop, send the password to be 100%
|
||||||
|
// certain that the mount hasn't done anything yet.
|
||||||
|
// then remember the device this dir is on and if that
|
||||||
|
// changes then we know that the mount has succeeded.
|
||||||
|
oldDevice = targetDir.st_dev;
|
||||||
|
write(aStdinPipe[PIPE_WRITE], password, strlen);
|
||||||
|
write(aStdinPipe[PIPE_WRITE], "\n", 1);
|
||||||
|
}
|
||||||
|
else if (oldDevice != targetDir.st_dev) {
|
||||||
|
ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(75));
|
||||||
|
}
|
||||||
|
|
||||||
|
close(aStdinPipe[PIPE_WRITE]);
|
||||||
|
if (!ok) {
|
||||||
|
printf("EncFS never did its thing. Wrong password?\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to kill it later.
|
||||||
|
* Which means we need to have another process that actually has the rights
|
||||||
|
* to kill it we can talk to.
|
||||||
|
* So, a pipe and a simple process that will 'kill' the encfs process later,
|
||||||
|
* on command it is!
|
||||||
|
*/
|
||||||
|
|
||||||
|
const auto encFsPid = pid;
|
||||||
|
int encFsWatchdogPipe[2];
|
||||||
|
if (pipe(encFsWatchdogPipe) < 0) {
|
||||||
|
perror("allocating pipe for encfs");
|
||||||
|
kill(encFsPid, SIGTERM);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
fprintf(stderr, "Runner: Failed to fork\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (pid == 0) {
|
||||||
|
close(encFsWatchdogPipe[PIPE_WRITE]);
|
||||||
|
renameThisProcess(m_processName, m_processNameSize, "watchdog-encfs");
|
||||||
|
|
||||||
|
char buf[10];
|
||||||
|
do {
|
||||||
|
auto size = read(encFsWatchdogPipe[PIPE_READ], &buf, sizeof(buf));
|
||||||
|
if (size < 0)
|
||||||
|
exit(0);
|
||||||
|
if (size >= 2) {
|
||||||
|
kill(encFsPid, SIGTERM);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
close(encFsWatchdogPipe[PIPE_READ]);
|
||||||
|
|
||||||
|
return encFsWatchdogPipe[PIPE_WRITE];
|
||||||
|
}
|
||||||
|
|
||||||
void renameThisProcess(char *nameBlob, int blobSize, const char *newName)
|
void renameThisProcess(char *nameBlob, int blobSize, const char *newName)
|
||||||
{
|
{
|
||||||
assert(nameBlob);
|
assert(nameBlob);
|
||||||
|
|||||||
@@ -34,8 +34,11 @@ private:
|
|||||||
void mkdirs(const std::filesystem::path &dir) const;
|
void mkdirs(const std::filesystem::path &dir) const;
|
||||||
int runInitScript();
|
int runInitScript();
|
||||||
|
|
||||||
|
int runEncFs(const char *password, int strlen) const;
|
||||||
|
|
||||||
const int m_outputFD;
|
const int m_outputFD;
|
||||||
uint32_t m_ownerUid = 0;
|
uint32_t m_ownerUid = 0;
|
||||||
|
uint32_t m_jailId = 0;
|
||||||
Message m_message;
|
Message m_message;
|
||||||
|
|
||||||
char *m_processName = nullptr;
|
char *m_processName = nullptr;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QCoreApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
// #define DEBUG_MESSAGE
|
// #define DEBUG_MESSAGE
|
||||||
|
|
||||||
@@ -163,8 +163,10 @@ static void mainListener(int x, char **y, int inputId, int outputId)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QCoreApplication app(x, y);
|
QApplication app(x, y);
|
||||||
app.setApplicationName("isolation-runner");
|
app.setApplicationName("isolation-runner");
|
||||||
|
app.setQuitOnLastWindowClosed(false); // avoid magic behavior
|
||||||
|
|
||||||
std::srand(std::time(0));
|
std::srand(std::time(0));
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addHelpOption(); // allows users to get an overview of options
|
parser.addHelpOption(); // allows users to get an overview of options
|
||||||
|
|||||||
Reference in New Issue
Block a user