[Libreoffice-commits] online.git: loolwsd/LOOLForKit.cpp loolwsd/LOOLKit.cpp loolwsd/LOOLKit.hpp loolwsd/LOOLWSD.cpp loolwsd/Makefile.am

Michael Meeks michael.meeks at collabora.com
Sat Apr 16 19:50:01 UTC 2016


 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.meeks at 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


More information about the Libreoffice-commits mailing list