From 732fd0b180e78e53b791c18dc39a18f1fa8e8e30 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 12 Oct 2015 17:45:21 +0200 Subject: [PATCH] lxcpp: Adding init process to UTS, PID, NET, IPC namespaces [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 | 13 +++++- libs/lxcpp/container-impl.cpp | 6 ++- libs/lxcpp/container-impl.hpp | 1 + libs/lxcpp/container.hpp | 2 + libs/lxcpp/guard/guard.cpp | 73 ++++++++++++++++++--------------- libs/lxcpp/guard/guard.hpp | 11 ++++- libs/lxcpp/guard/main.cpp | 11 +++-- tests/unit_tests/lxcpp/ut-container.cpp | 1 + 8 files changed, 78 insertions(+), 40 deletions(-) diff --git a/libs/lxcpp/container-config.hpp b/libs/lxcpp/container-config.hpp index c84b4ef..9990bdc 100644 --- a/libs/lxcpp/container-config.hpp +++ b/libs/lxcpp/container-config.hpp @@ -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 ) }; diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index d3258aa..5f0da35 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -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 diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp index 041303b..846536e 100644 --- a/libs/lxcpp/container-impl.hpp +++ b/libs/lxcpp/container-impl.hpp @@ -56,6 +56,7 @@ public: void setTerminalCount(const unsigned int count); const std::vector& getNamespaces() const; + void setNamespaces(const int namespaces); // Execution actions void start(); diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp index e3d537f..ba32e64 100644 --- a/libs/lxcpp/container.hpp +++ b/libs/lxcpp/container.hpp @@ -26,6 +26,7 @@ #include "lxcpp/network-config.hpp" #include "lxcpp/logger-config.hpp" + #include #include @@ -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; diff --git a/libs/lxcpp/guard/guard.cpp b/libs/lxcpp/guard/guard.cpp index 28e572a..4f56771 100644 --- a/libs/lxcpp/guard/guard.cpp +++ b/libs/lxcpp/guard/guard.cpp @@ -32,64 +32,71 @@ #include #include - namespace lxcpp { +namespace { -void startContainer(const ContainerConfig &cfg) +int startContainer(void* data) { - lxcpp::execve(cfg.mInit); + ContainerConfig& config = *static_cast(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 diff --git a/libs/lxcpp/guard/guard.hpp b/libs/lxcpp/guard/guard.hpp index 78457ae..741d72a 100644 --- a/libs/lxcpp/guard/guard.hpp +++ b/libs/lxcpp/guard/guard.hpp @@ -28,11 +28,20 @@ #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 diff --git a/libs/lxcpp/guard/main.cpp b/libs/lxcpp/guard/main.cpp index 78c7476..ff26418 100644 --- a/libs/lxcpp/guard/main.cpp +++ b/libs/lxcpp/guard/main.cpp @@ -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; + } } diff --git a/tests/unit_tests/lxcpp/ut-container.cpp b/tests/unit_tests/lxcpp/ut-container.cpp index 1c1a76c..17eee93 100644 --- a/tests/unit_tests/lxcpp/ut-container.cpp +++ b/tests/unit_tests/lxcpp/ut-container.cpp @@ -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()); } -- 2.7.4