loolwsd/LOOLForKit.cpp | 8 +- loolwsd/LOOLKit.cpp | 176 ++++++++++++++++++++++++++----------------------- loolwsd/LOOLKit.hpp | 3 loolwsd/LOOLWSD.cpp | 16 ++++ loolwsd/Makefile.am | 6 + 5 files changed, 124 insertions(+), 85 deletions(-)
New commits: commit 6388298a049fb40d7f1994f9395558777c5bbc09 Author: Michael Meeks <michael.me...@collabora.com> Date: Sat Apr 16 20:44:53 2016 +0100 Attempt at a --nocaps argument to run with no caps, ie. under valgrind. diff --git a/loolwsd/LOOLForKit.cpp b/loolwsd/LOOLForKit.cpp index ffebf56..4d7ba5f 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 7f55ec9..1a91bb6 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 a898166..2f43022 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 0a06948..f954a53 100644 --- a/loolwsd/LOOLWSD.cpp +++ b/loolwsd/LOOLWSD.cpp @@ -149,6 +149,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; @@ -1213,6 +1214,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) @@ -1255,6 +1261,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 @@ -1283,7 +1291,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 e3c5f7a..39c5071 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 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits