diff options
author | Ashod Nakashian <ashod.nakashian@collabora.co.uk> | 2020-08-23 12:11:23 -0400 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2020-08-25 07:58:30 +0200 |
commit | 29a5a1f1e97e10aa6f9bdbed0b1062e2ab4e128b (patch) | |
tree | cfd3286926eaad338ef2fb96ac1f75cdc2dbc9bc /kit/Kit.cpp | |
parent | b72146bfaca36b05ca12672582380abc55a4ebde (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.cpp | 114 |
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); |