summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2016-04-16 20:44:53 +0100
committerMichael Meeks <michael.meeks@collabora.com>2016-04-16 20:44:53 +0100
commitc06a7caf61b69ad2de74b07310570503a17c2400 (patch)
tree7004ce60c66f6c7bd3d42b03bf2364c51989c0db
parenta66e73aeb0789a87c6948e6c1e9a2fc3e13b3aa1 (diff)
Attempt at a --nocaps argument to run with no caps, ie. under valgrind.private/mmeeks/unitbits
-rw-r--r--loolwsd/LOOLForKit.cpp8
-rw-r--r--loolwsd/LOOLKit.cpp176
-rw-r--r--loolwsd/LOOLKit.hpp3
-rw-r--r--loolwsd/LOOLWSD.cpp16
-rw-r--r--loolwsd/Makefile.am6
5 files changed, 124 insertions, 85 deletions
diff --git a/loolwsd/LOOLForKit.cpp b/loolwsd/LOOLForKit.cpp
index ffebf5652..4d7ba5f28 100644
--- a/loolwsd/LOOLForKit.cpp
+++ b/loolwsd/LOOLForKit.cpp
@@ -44,6 +44,7 @@ using Poco::Thread;
using Poco::Timestamp;
using Poco::Util::Application;
+static bool NoCapsForKit = false;
static std::string UnitTestLibrary;
static std::atomic<unsigned> ForkCounter( 0 );
@@ -117,7 +118,7 @@ static int createLibreOfficeKit(const std::string& childRoot,
Thread::sleep(std::stoul(std::getenv("SLEEPKITFORDEBUGGER")) * 1000);
}
- lokit_main(childRoot, sysTemplate, loTemplate, loSubPath);
+ lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, NoCapsForKit);
}
else
{
@@ -213,6 +214,11 @@ int main(int argc, char** argv)
eq = std::strchr(cmd, '=');
UnitTestLibrary = std::string(eq+1);
}
+ // we are running in no-privilege mode - with no chroot etc.
+ else if (std::strstr(cmd, "--nocaps") == cmd)
+ {
+ NoCapsForKit = true;
+ }
#endif
}
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 7f55ec966..1a91bb636 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -847,7 +847,8 @@ namespace {
void lokit_main(const std::string& childRoot,
const std::string& sysTemplate,
const std::string& loTemplate,
- const std::string& loSubPath)
+ const std::string& loSubPath,
+ bool noCapabilities)
{
// Reinitialize logging when forked.
Log::initialize("kit");
@@ -874,102 +875,112 @@ void lokit_main(const std::string& childRoot,
Util::setTerminationSignals();
Util::setFatalSignals();
- static const std::string instdir_path = "/" + loSubPath + "/program";
- LibreOfficeKit* loKit = nullptr;
+ std::string instdir_path;
+ Path jailPath;
+ bool bRunInsideJail = !noCapabilities;
try
{
- const Path jailPath = Path::forDirectory(childRoot + Path::separator() + jailId);
- Log::info("Jail path: " + jailPath.toString());
- File(jailPath).createDirectories();
+ if (bRunInsideJail)
+ {
+ instdir_path = "/" + loSubPath + "/program";
- // Create a symlink inside the jailPath so that the absolute pathname loTemplate, when
- // interpreted inside a chroot at jailPath, points to loSubPath (relative to the chroot).
- symlinkPathToJail(jailPath, loTemplate, loSubPath);
+ jailPath = Path::forDirectory(childRoot + Path::separator() + jailId);
+ Log::info("Jail path: " + jailPath.toString());
+ File(jailPath).createDirectories();
- // Font paths can end up as realpaths so match that too.
- char *resolved = realpath(loTemplate.c_str(), NULL);
- if (resolved)
- {
- if (strcmp(loTemplate.c_str(), resolved))
- symlinkPathToJail(jailPath, std::string(resolved), loSubPath);
- free (resolved);
- }
+ // Create a symlink inside the jailPath so that the absolute pathname loTemplate, when
+ // interpreted inside a chroot at jailPath, points to loSubPath (relative to the chroot).
+ symlinkPathToJail(jailPath, loTemplate, loSubPath);
- Path jailLOInstallation(jailPath, loSubPath);
- jailLOInstallation.makeDirectory();
- File(jailLOInstallation).createDirectory();
+ // Font paths can end up as realpaths so match that too.
+ char *resolved = realpath(loTemplate.c_str(), NULL);
+ if (resolved)
+ {
+ if (strcmp(loTemplate.c_str(), resolved))
+ symlinkPathToJail(jailPath, std::string(resolved), loSubPath);
+ free (resolved);
+ }
- // Copy (link) LO installation and other necessary files into it from the template.
- bool bLoopMounted = false;
- if (getenv("LOOL_BIND_MOUNT"))
- {
- Path usrSrcPath(sysTemplate, "usr");
- Path usrDestPath(jailPath, "usr");
- File(usrDestPath).createDirectory();
- std::string mountCommand =
- std::string("loolmount ") +
- usrSrcPath.toString() +
- std::string(" ") +
- usrDestPath.toString();
- Log::debug("Initializing jail bind mount.");
- bLoopMounted = !system(mountCommand.c_str());
- Log::debug("Initialized jail bind mount.");
- }
- linkOrCopy(sysTemplate, jailPath,
- bLoopMounted ? COPY_NO_USR : COPY_ALL);
- linkOrCopy(loTemplate, jailLOInstallation, COPY_LO);
+ Path jailLOInstallation(jailPath, loSubPath);
+ jailLOInstallation.makeDirectory();
+ File(jailLOInstallation).createDirectory();
- // We need this because sometimes the hostname is not resolved
- const auto networkFiles = {"/etc/host.conf", "/etc/hosts", "/etc/nsswitch.conf", "/etc/resolv.conf"};
- for (const auto& filename : networkFiles)
- {
- const auto etcPath = Path(jailPath, filename).toString();
- const File networkFile(filename);
- if (networkFile.exists() && !File(etcPath).exists())
+ // Copy (link) LO installation and other necessary files into it from the template.
+ bool bLoopMounted = false;
+ if (getenv("LOOL_BIND_MOUNT"))
{
- networkFile.copyTo(etcPath);
+ Path usrSrcPath(sysTemplate, "usr");
+ Path usrDestPath(jailPath, "usr");
+ File(usrDestPath).createDirectory();
+ std::string mountCommand =
+ std::string("loolmount ") +
+ usrSrcPath.toString() +
+ std::string(" ") +
+ usrDestPath.toString();
+ Log::debug("Initializing jail bind mount.");
+ bLoopMounted = !system(mountCommand.c_str());
+ Log::debug("Initialized jail bind mount.");
}
- }
+ linkOrCopy(sysTemplate, jailPath,
+ bLoopMounted ? COPY_NO_USR : COPY_ALL);
+ linkOrCopy(loTemplate, jailLOInstallation, COPY_LO);
- Log::debug("Initialized jail files.");
+ // We need this because sometimes the hostname is not resolved
+ const auto networkFiles = {"/etc/host.conf", "/etc/hosts", "/etc/nsswitch.conf", "/etc/resolv.conf"};
+ for (const auto& filename : networkFiles)
+ {
+ const auto etcPath = Path(jailPath, filename).toString();
+ const File networkFile(filename);
+ if (networkFile.exists() && !File(etcPath).exists())
+ {
+ networkFile.copyTo(etcPath);
+ }
+ }
- // Create the urandom and random devices
- File(Path(jailPath, "/dev")).createDirectory();
- if (mknod((jailPath.toString() + "/dev/random").c_str(),
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
- makedev(1, 8)) != 0)
- {
- Log::syserror("mknod(" + jailPath.toString() + "/dev/random) failed.");
+ Log::debug("Initialized jail files.");
- }
- if (mknod((jailPath.toString() + "/dev/urandom").c_str(),
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
- makedev(1, 9)) != 0)
- {
- Log::syserror("mknod(" + jailPath.toString() + "/dev/urandom) failed.");
- }
+ // Create the urandom and random devices
+ File(Path(jailPath, "/dev")).createDirectory();
+ if (mknod((jailPath.toString() + "/dev/random").c_str(),
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
+ makedev(1, 8)) != 0)
+ {
+ Log::syserror("mknod(" + jailPath.toString() + "/dev/random) failed.");
+ }
+ if (mknod((jailPath.toString() + "/dev/urandom").c_str(),
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
+ makedev(1, 9)) != 0)
+ {
+ Log::syserror("mknod(" + jailPath.toString() + "/dev/urandom) failed.");
+ }
- Log::info("chroot(\"" + jailPath.toString() + "\")");
- if (chroot(jailPath.toString().c_str()) == -1)
- {
- Log::syserror("chroot(\"" + jailPath.toString() + "\") failed.");
- std::_Exit(Application::EXIT_SOFTWARE);
- }
+ Log::info("chroot(\"" + jailPath.toString() + "\")");
+ if (chroot(jailPath.toString().c_str()) == -1)
+ {
+ Log::syserror("chroot(\"" + jailPath.toString() + "\") failed.");
+ std::_Exit(Application::EXIT_SOFTWARE);
+ }
- if (chdir("/") == -1)
- {
- Log::syserror("chdir(\"/\") in jail failed.");
- std::_Exit(Application::EXIT_SOFTWARE);
- }
+ if (chdir("/") == -1)
+ {
+ Log::syserror("chdir(\"/\") in jail failed.");
+ std::_Exit(Application::EXIT_SOFTWARE);
+ }
- dropCapability(CAP_SYS_CHROOT);
- dropCapability(CAP_MKNOD);
- dropCapability(CAP_FOWNER);
+ dropCapability(CAP_SYS_CHROOT);
+ dropCapability(CAP_MKNOD);
+ dropCapability(CAP_FOWNER);
- Log::debug("Initialized jail nodes, dropped caps.");
+ Log::debug("Initialized jail nodes, dropped caps.");
+ }
+ else // noCapabilities set
+ {
+ Log::info("Using template " + loTemplate + " as install subpath - skipping jail setup");
+ instdir_path = "/" + loTemplate + "/program";
+ }
- loKit = lok_init_2(instdir_path.c_str(), "file:///user");
+ LibreOfficeKit* loKit = lok_init_2(instdir_path.c_str(), "file:///user");
if (loKit == nullptr)
{
Log::error("LibreOfficeKit initialization failed. Exiting.");
@@ -1042,8 +1053,11 @@ void lokit_main(const std::string& childRoot,
return TerminationFlag;
});
- // Cleanup jail.
- Util::removeFile(jailPath, true);
+ // Cleanup a jail if we created one
+ if (bRunInsideJail && !jailPath.isRelative())
+ {
+ Util::removeFile(jailPath, true);
+ }
}
catch (const Exception& exc)
{
diff --git a/loolwsd/LOOLKit.hpp b/loolwsd/LOOLKit.hpp
index a8981662d..2f4302248 100644
--- a/loolwsd/LOOLKit.hpp
+++ b/loolwsd/LOOLKit.hpp
@@ -12,7 +12,8 @@
void lokit_main(const std::string& childRoot,
const std::string& sysTemplate,
const std::string& loTemplate,
- const std::string& loSubPath);
+ const std::string& loSubPath,
+ bool noCapabilities);
bool globalPreinit(const std::string &loTemplate);
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 802850b44..0b0155cc4 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -147,6 +147,7 @@ int ClientPortNumber = DEFAULT_CLIENT_PORT_NUMBER;
/// New LOK child processes ready to host documents.
//TODO: Move to a more sensible namespace.
static bool DisplayVersion = false;
+static bool NoCapsForKit = false;
static std::vector<std::shared_ptr<ChildProcess>> newChildren;
static std::mutex newChildrenMutex;
static std::condition_variable newChildrenCV;
@@ -1216,6 +1217,11 @@ void LOOLWSD::defineOptions(OptionSet& optionSet)
.repeatable(false)
.argument("unitlib"));
+ optionSet.addOption(Option("nocaps", "", "Use a non-privileged forkit for valgrinding.")
+ .required(false)
+ .repeatable(false)
+ .argument("nocaps"));
+
optionSet.addOption(Option("careerspan", "", "How many seconds to run.")
.required(false)
.repeatable(false)
@@ -1258,6 +1264,8 @@ void LOOLWSD::handleOption(const std::string& optionName,
#if ENABLE_DEBUG
else if (optionName == "unitlib")
UnitTestLibrary = value;
+ else if (optionName == "nocaps")
+ NoCapsForKit = true;
else if (optionName == "careerspan")
careerSpanSeconds = std::stoi(value);
#endif
@@ -1286,7 +1294,13 @@ Process::PID LOOLWSD::createForKit()
if (DisplayVersion)
args.push_back("--version");
- const std::string forKitPath = Path(Application::instance().commandPath()).parent().toString() + "loolforkit";
+ std::string forKitPath = Path(Application::instance().commandPath()).parent().toString() + "loolforkit";
+
+ if (NoCapsForKit)
+ {
+ forKitPath = forKitPath + std::string("-nocaps");
+ args.push_back("--nocaps");
+ }
Log::info("Launching forkit process: " + forKitPath + " " +
Poco::cat(std::string(" "), args.begin(), args.end()));
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index e3c5f7a88..39c5071ed 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -49,7 +49,8 @@ loolwsd_SOURCES = Admin.cpp \
noinst_PROGRAMS = connect \
loadtest \
- lokitclient
+ lokitclient \
+ loolforkit-nocaps
loadtest_SOURCES = LoadTest.cpp \
Log.cpp \
@@ -71,6 +72,9 @@ loolforkit_SOURCES = LOOLForKit.cpp \
LOOLKit.cpp \
$(shared_sources)
+# build a binary with no caps to help debugging
+loolforkit_nocaps_SOURCES = $(loolforkit_SOURCES)
+
loolmount_SOURCES = loolmount.c
loolmap_SOURCES = loolmap.c