lxcpp: Adding init process to UTS, PID, NET, IPC namespaces 31/49331/3
authorJan Olszak <j.olszak@samsung.com>
Mon, 12 Oct 2015 15:45:21 +0000 (17:45 +0200)
committerJan Olszak <j.olszak@samsung.com>
Wed, 14 Oct 2015 06:12:09 +0000 (08:12 +0200)
[Feature]       Starting init in some namespaces.
                MNT and USER need more work.
[Cause]         N/A
[Solution]      Refactored Guard
[Verification]  Build, install and run tests

Change-Id: I3c5ec5c833da34c9ece6acf2c4965e8c57ab966d

libs/lxcpp/container-config.hpp
libs/lxcpp/container-impl.cpp
libs/lxcpp/container-impl.hpp
libs/lxcpp/container.hpp
libs/lxcpp/guard/guard.cpp
libs/lxcpp/guard/guard.hpp
libs/lxcpp/guard/main.cpp
tests/unit_tests/lxcpp/ut-container.cpp

index c84b4ef..9990bdc 100644 (file)
@@ -109,7 +109,15 @@ struct ContainerConfig {
      */
     TerminalsConfig mTerminals;
 
-    ContainerConfig() : mGuardPid(-1), mInitPid(-1) {}
+    /**
+     * Namespace types used to create the container
+     *
+     * Set: setNamespaces()
+     * Get: none
+     */
+    int mNamespaces;
+
+    ContainerConfig() : mGuardPid(-1), mInitPid(-1), mNamespaces(0) {}
 
     CONFIG_REGISTER
     (
@@ -119,7 +127,8 @@ struct ContainerConfig {
         mInitPid,
         mInit,
         mLogger,
-        mTerminals
+        mTerminals,
+        mNamespaces
     )
 };
 
index d3258aa..5f0da35 100644 (file)
@@ -25,7 +25,6 @@
 #include "lxcpp/exception.hpp"
 #include "lxcpp/process.hpp"
 #include "lxcpp/filesystem.hpp"
-#include "lxcpp/namespace.hpp"
 #include "lxcpp/capability.hpp"
 #include "lxcpp/commands/attach.hpp"
 #include "lxcpp/commands/start.hpp"
@@ -169,6 +168,11 @@ void ContainerImpl::setTerminalCount(const unsigned int count)
     mConfig.mTerminals.count = count;
 }
 
+void ContainerImpl::setNamespaces(const int namespaces)
+{
+    mConfig.mNamespaces = namespaces;
+}
+
 void ContainerImpl::start()
 {
     // TODO: check config consistency and completeness somehow
index 041303b..846536e 100644 (file)
@@ -56,6 +56,7 @@ public:
     void setTerminalCount(const unsigned int count);
 
     const std::vector<Namespace>& getNamespaces() const;
+    void setNamespaces(const int namespaces);
 
     // Execution actions
     void start();
index e3d537f..ba32e64 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "lxcpp/network-config.hpp"
 #include "lxcpp/logger-config.hpp"
+
 #include <sys/types.h>
 
 #include <string>
@@ -62,6 +63,7 @@ public:
                            const std::string &arg = "") = 0;
 
     virtual void setTerminalCount(const unsigned int count) = 0;
+    virtual void setNamespaces(const int namespaces) = 0;
 
     // Execution actions
     virtual void start() = 0;
index 28e572a..4f56771 100644 (file)
 #include <unistd.h>
 #include <sys/wait.h>
 
-
 namespace lxcpp {
 
+namespace {
 
-void startContainer(const ContainerConfig &cfg)
+int startContainer(void* data)
 {
-    lxcpp::execve(cfg.mInit);
+    ContainerConfig& config = *static_cast<ContainerConfig*>(data);
+
+    // TODO: container preparation part 2
+
+    PrepGuestTerminal terminals(config.mTerminals);
+    terminals.execute();
+
+    lxcpp::execve(config.mInit);
+
+    return EXIT_FAILURE;
 }
 
-int startGuard(int channelFD)
+} // namespace
+
+
+Guard::Guard(const int channelFD)
+    : mChannel(channelFD)
 {
-    ContainerConfig cfg;
-    utils::Channel channel(channelFD);
-    channel.setCloseOnExec(true);
-    config::loadFromFD(channel.getFD(), cfg);
+    mChannel.setCloseOnExec(true);
+    config::loadFromFD(mChannel.getFD(), mConfig);
 
-    logger::setupLogger(cfg.mLogger.getType(),
-                        cfg.mLogger.getLevel(),
-                        cfg.mLogger.getArg());
+    logger::setupLogger(mConfig.mLogger.getType(),
+                        mConfig.mLogger.getLevel(),
+                        mConfig.mLogger.getArg());
 
-    LOGD("Guard started, config & logging restored");
+    LOGD("Config & logging restored");
 
     try {
         LOGD("Setting the guard process title");
-        const std::string title = "[LXCPP] " + cfg.mName + " " + cfg.mRootPath;
+        const std::string title = "[LXCPP] " + mConfig.mName + " " + mConfig.mRootPath;
         setProcTitle(title);
     } catch (std::exception &e) {
         // Ignore, this is optional
         LOGW("Failed to set the guard process title: " << e.what());
     }
+}
 
-    // TODO: container preparation part 1
-
-    // TODO: switch to clone
-    LOGD("Forking container's init process");
-    pid_t pid = lxcpp::fork();
-
-    if (pid == 0) {
-        // TODO: container preparation part 2
+Guard::~Guard()
+{
+}
 
-        PrepGuestTerminal terminals(cfg.mTerminals);
-        terminals.execute();
+int Guard::execute()
+{
+    // TODO: container preparation part 1
 
-        startContainer(cfg);
-        ::_exit(EXIT_FAILURE);
-    }
+    const pid_t initPid = lxcpp::clone(startContainer,
+                                       &mConfig,
+                                       mConfig.mNamespaces);
 
-    cfg.mGuardPid = ::getpid();
-    cfg.mInitPid = pid;
+    mConfig.mGuardPid = ::getpid();
+    mConfig.mInitPid = initPid;
 
-    channel.write(cfg.mGuardPid);
-    channel.write(cfg.mInitPid);
-    channel.shutdown();
+    mChannel.write(mConfig.mGuardPid);
+    mChannel.write(mConfig.mInitPid);
+    mChannel.shutdown();
 
-    int status = lxcpp::waitpid(pid);
+    int status = lxcpp::waitpid(initPid);
     LOGD("Init exited with status: " << status);
     return status;
 }
 
-
 } // namespace lxcpp
index 78457ae..741d72a 100644 (file)
 #include "lxcpp/container-config.hpp"
 #include "utils/channel.hpp"
 
+
 namespace lxcpp {
 
+class Guard {
+public:
+    Guard(const int channelFD);
+    ~Guard();
 
-int startGuard(int channelFD);
+    int execute();
 
+private:
+    utils::Channel mChannel;
+    ContainerConfig mConfig;
+};
 
 } // namespace lxcpp
 
index 78c7476..ff26418 100644 (file)
@@ -35,8 +35,6 @@ int main(int argc, char *argv[])
         ::_exit(EXIT_FAILURE);
     }
 
-    int channelFD = std::stoi(argv[1]);
-
     // NOTE: this might not be required now, but I leave it here not to forget.
     // We need to investigate this with vasum and think about possibility of
     // poorly written software that leaks file descriptors and might use LXCPP.
@@ -48,5 +46,12 @@ int main(int argc, char *argv[])
     }
 #endif
 
-    return lxcpp::startGuard(channelFD);
+    try {
+        int fd = std::stoi(argv[1]);
+        lxcpp::Guard guard(fd);
+        return guard.execute();
+    } catch(std::exception& e) {
+        // LOGE("Unexpected: " << utils::getTypeName(e) << ": " << e.what());
+        return EXIT_FAILURE;
+    }
 }
index 1c1a76c..17eee93 100644 (file)
@@ -116,6 +116,7 @@ BOOST_AUTO_TEST_CASE(StartStop)
     BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
                                       logger::LogLevel::DEBUG,
                                       LOGGER_FILE));
+    BOOST_CHECK_NO_THROW(c->setNamespaces(CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWUTS));
     BOOST_CHECK_NO_THROW(c->start());
     BOOST_CHECK_NO_THROW(c->stop());
 }