summaryrefslogtreecommitdiff
path: root/kit/Kit.cpp
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2020-08-23 12:11:23 -0400
committerAndras Timar <andras.timar@collabora.com>2020-08-25 07:58:30 +0200
commit29a5a1f1e97e10aa6f9bdbed0b1062e2ab4e128b (patch)
treecfd3286926eaad338ef2fb96ac1f75cdc2dbc9bc /kit/Kit.cpp
parentb72146bfaca36b05ca12672582380abc55a4ebde (diff)
wsd: move jail setup to the script to support readonly systemplate
We now gracefully fallback to copying when/if systemplate is readonly. The bulk of the change is to support proper cleanup in both cases. First, we had to move as much of the jail bootstrapping into the loolwsd-systemplate-setup script, so systemplate will be as complete as possible before it is locked down. Next, we needed to update the jail with graceful fallback to linking/copying upon failure. For that, the jail setup logic in Kit.cpp has been reworked to support not just update failures, but also more comprehensive mounting failures as well. Finally, jail cleanup now is seamless. To support proper cleanup when we had mounting enabled but had to fallback, we mark jails that aren't mounted so we can 'rm -rf' the contents safely and without fear or causing undue damage (as unlikely as that is, technically we wouldn't want to rm systemplate files, if mounting read-only had failed). There are a few minor refactorings of JailUtil to make it cleaner and more robust. Change-Id: Iac34869cb84f45acf64fbbc46d46898367b496d2 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/101260 Tested-by: Jenkins Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'kit/Kit.cpp')
-rw-r--r--kit/Kit.cpp114
1 files changed, 74 insertions, 40 deletions
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 2a312b986..30cd4e5f8 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -11,6 +11,7 @@
* a document editing session.
*/
+#include <Poco/File.h>
#include <config.h>
#include <dlfcn.h>
@@ -2119,9 +2120,10 @@ void lokit_main(
{
#if !MOBILEAPP
const Path jailPath = Path::forDirectory(childRoot + '/' + jailId);
- LOG_INF("Jail path: " << jailPath.toString());
+ const std::string jailPathStr = jailPath.toString();
+ LOG_INF("Jail path: " << jailPathStr);
File(jailPath).createDirectories();
- chmod(jailPath.toString().c_str(), S_IXUSR | S_IWUSR | S_IRUSR);
+ chmod(jailPathStr.c_str(), S_IXUSR | S_IWUSR | S_IRUSR);
if (!ChildSession::NoCapsForKit)
{
@@ -2131,66 +2133,96 @@ void lokit_main(
userdir_url = "file:///tmp/user";
instdir_path = '/' + loSubPath + "/program";
- // Copy (link) LO installation and other necessary files into it from the template.
- if (std::getenv("LOOL_BIND_MOUNT"))
- {
- const std::string destPath = jailPath.toString();
- LOG_INF("Mounting " << sysTemplate << " -> " << destPath);
- if (!JailUtil::bind(sysTemplate, destPath))
+ Poco::Path jailLOInstallation(jailPath, loSubPath);
+ jailLOInstallation.makeDirectory();
+ const std::string loJailDestPath = jailLOInstallation.toString();
+
+ // The bind-mount implementation: inlined here to mirror
+ // the fallback link/copy version bellow.
+ const auto mountJail = [&]() -> bool {
+ // Mount sysTemplate for the jail directory.
+ LOG_INF("Mounting " << sysTemplate << " -> " << jailPathStr);
+ if (!JailUtil::bind(sysTemplate, jailPathStr)
+ || !JailUtil::remountReadonly(sysTemplate, jailPathStr))
{
- LOG_WRN("Failed to mount [" << sysTemplate << "] -> [" << destPath
+ LOG_WRN("Failed to mount [" << sysTemplate << "] -> [" << jailPathStr
<< "], will link/copy contents.");
- linkOrCopy(sysTemplate, destPath, LinkOrCopyType::All);
+ return false;
}
- else
- JailUtil::remountReadonly(sysTemplate, jailPath.toString());
- // Mount lotemplate inside it.
- const std::string loDestPath = Poco::Path(jailPath, "lo").toString();
- LOG_INF("Mounting " << loTemplate << " -> " << loDestPath);
- Poco::File(loDestPath).createDirectories();
- if (!JailUtil::bind(loTemplate, loDestPath))
+ // Mount loTemplate inside it.
+ LOG_INF("Mounting " << loTemplate << " -> " << loJailDestPath);
+ Poco::File(loJailDestPath).createDirectories();
+ if (!JailUtil::bind(loTemplate, loJailDestPath)
+ || !JailUtil::remountReadonly(loTemplate, loJailDestPath))
{
- LOG_WRN("Failed to mount [" << loTemplate << "] -> [" << loDestPath
+ LOG_WRN("Failed to mount [" << loTemplate << "] -> [" << loJailDestPath
<< "], will link/copy contents.");
- linkOrCopy(sysTemplate, loDestPath, LinkOrCopyType::LO);
+ return false;
}
- else
- JailUtil::remountReadonly(loTemplate, loDestPath);
- // hard-random tmpdir inside the jail / root
+ // Hard-random tmpdir inside the jail for added sercurity.
const std::string tempRoot = Poco::Path(childRoot, "tmp").toString();
Poco::File(tempRoot).createDirectories();
const std::string tmpSubDir = Util::createRandomTmpDir(tempRoot);
const std::string jailTmpDir = Poco::Path(jailPath, "tmp").toString();
+ LOG_INF("Mounting random temp dir " << tmpSubDir << " -> " << jailTmpDir);
if (!JailUtil::bind(tmpSubDir, jailTmpDir))
{
- LOG_ERR("Failed to bind tmp dir in jail.");
+ LOG_WRN("Failed to mount [" << tmpSubDir << "] -> [" << jailTmpDir
+ << "], will link/copy contents.");
+ return false;
}
- JailUtil::setupJailDevNodes(destPath + "/tmp");
+ return true;
+ };
+
+ // Copy (link) LO installation and other necessary files into it from the template.
+ bool bindMount = JailUtil::isBindMountingEnabled();
+ if (bindMount)
+ {
+ if (!mountJail())
+ {
+ LOG_INF("Cleaning up jail before linking/copying.");
+ JailUtil::removeJail(jailPathStr);
+ bindMount = false;
+ JailUtil::disableBindMounting();
+ }
}
- else
+
+ if (!bindMount)
{
- linkOrCopy(sysTemplate, jailPath, LinkOrCopyType::All);
+ LOG_INF("Mounting is disabled, will link/copy " << sysTemplate << " -> "
+ << jailPathStr);
- Poco::Path jailLOInstallation(jailPath, loSubPath);
- jailLOInstallation.makeDirectory();
- Poco::File(jailLOInstallation).createDirectory();
- linkOrCopy(loTemplate, jailLOInstallation, LinkOrCopyType::LO);
+ linkOrCopy(sysTemplate, jailPath, LinkOrCopyType::All);
- JailUtil::setupJailDevNodes(Poco::Path(jailPath, "/tmp").toString());
+ linkOrCopy(loTemplate, loJailDestPath, LinkOrCopyType::LO);
// Update the dynamic files inside the jail.
- if (!JailUtil::SysTemplate::updateDynamicFiles(jailPath.toString()))
+ if (!JailUtil::SysTemplate::updateDynamicFiles(jailPathStr))
{
- LOG_WRN("Failed to update the dynamic files in the jail ["
- << jailPath.toString() << "]. Some functionality may be missing.");
+ LOG_WRN(
+ "Failed to update the dynamic files in the jail ["
+ << jailPathStr
+ << "]. If the systemplate directory is owned by a superuser or is "
+ "read-only, running the installation scripts with the owner's account "
+ "should update these files. Some functionality may be missing.");
}
+
+ // Create a file to mark this a copied jail.
+ JailUtil::markJailCopied(jailPathStr);
}
+ // Setup the devices inside /tmp and set TMPDIR.
+ JailUtil::setupJailDevNodes(Poco::Path(jailPath, "/tmp").toString());
::setenv("TMPDIR", "/tmp", 1);
+ // HOME must be writable, so create it in /tmp.
+ constexpr const char* HomePathInJail = "/tmp/home";
+ Poco::File(Poco::Path(jailPath, HomePathInJail)).createDirectories();
+ ::setenv("HOME", HomePathInJail, 1);
+
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - jailSetupStartTime)
.count();
@@ -2200,10 +2232,10 @@ void lokit_main(
if (ProcSMapsFile < 0)
LOG_SYS("Failed to open /proc/self/smaps. Memory stats will be missing.");
- LOG_INF("chroot(\"" << jailPath.toString() << "\")");
- if (chroot(jailPath.toString().c_str()) == -1)
+ LOG_INF("chroot(\"" << jailPathStr << "\")");
+ if (chroot(jailPathStr.c_str()) == -1)
{
- LOG_SFL("chroot(\"" << jailPath.toString() << "\") failed.");
+ LOG_SFL("chroot(\"" << jailPathStr << "\") failed.");
Log::shutdown();
std::_Exit(EX_SOFTWARE);
}
@@ -2223,8 +2255,9 @@ void lokit_main(
}
else // noCapabilities set
{
- LOG_ERR("Security warning - using template " << loTemplate << " as install subpath - skipping chroot jail setup");
- userdir_url = "file:///" + jailPath.toString() + "/tmp/user";
+ LOG_ERR("Security warning - using template "
+ << loTemplate << " as install subpath - skipping chroot jail setup");
+ userdir_url = "file:///" + jailPathStr + "/tmp/user";
instdir_path = '/' + loTemplate + "/program";
}
@@ -2243,7 +2276,8 @@ void lokit_main(
#endif
if (!kit)
{
- kit = (initFunction ? initFunction(instdir, userdir) : lok_init_2(instdir, userdir));
+ kit = (initFunction ? initFunction(instdir, userdir)
+ : lok_init_2(instdir, userdir));
}
loKit = std::make_shared<lok::Office>(kit);