This is an automated email from the ASF dual-hosted git repository. gilbert pushed a commit to branch 1.6.x in repository https://gitbox.apache.org/repos/asf/mesos.git
commit cdf042e534caaba9c835f8eb2340ca1acd5fda79 Author: Gilbert Song <[email protected]> AuthorDate: Mon Feb 11 12:51:24 2019 -0800 Cloned a sealed file of launcher binary. Cloned this binary during mesos containerizer create and command executor launch. This change would copy the mesos-containerizer binary in memory, which helps avoid the binary being overwritten. Review: https://reviews.apache.org/r/69947/ (cherry picked from commit f7407d3d5f0fe7d5c9a06774921de514012a54da) --- src/launcher/executor.cpp | 23 +++++++++++++++++-- src/slave/containerizer/mesos/containerizer.cpp | 30 +++++++++++++++++++++++-- src/slave/containerizer/mesos/containerizer.hpp | 18 ++++++++++++--- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/launcher/executor.cpp b/src/launcher/executor.cpp index 3f606e5..ec12b89 100644 --- a/src/launcher/executor.cpp +++ b/src/launcher/executor.cpp @@ -82,6 +82,10 @@ #include "internal/devolve.hpp" #include "internal/evolve.hpp" +#ifdef __linux__ +#include "linux/memfd.hpp" +#endif // __linux__ + #include "logging/logging.hpp" #include "messages/messages.hpp" @@ -478,11 +482,26 @@ protected: launchFlags.launch_info = JSON::protobuf(launchInfo); + // Determine the mesos containerizer binary depends on whether we + // need to clone and seal it on linux. + string initPath = path::join(launcherDir, MESOS_CONTAINERIZER); +#ifdef __linux__ + // Clone the launcher binary in memory for security concerns. + Try<int_fd> memFd = memfd::cloneSealedFile(initPath); + if (memFd.isError()) { + ABORT( + "Failed to clone a sealed file '" + initPath + "' in memory: " + + memFd.error()); + } + + initPath = "/proc/self/fd/" + stringify(memFd.get()); +#endif // __linux__ + // TODO(tillt): Consider using a flag allowing / disallowing the // log output of possibly sensitive data. See MESOS-7292. string commandString = strings::format( "%s %s <POSSIBLY-SENSITIVE-DATA>", - path::join(launcherDir, MESOS_CONTAINERIZER), + initPath, MesosContainerizerLaunch::NAME).get(); LOG(INFO) << "Running '" << commandString << "'"; @@ -508,7 +527,7 @@ protected: } Try<Subprocess> s = subprocess( - path::join(launcherDir, MESOS_CONTAINERIZER), + initPath, argv, Subprocess::FD(STDIN_FILENO), Subprocess::FD(STDOUT_FILENO), diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp index c9af06c..7f00084 100644 --- a/src/slave/containerizer/mesos/containerizer.cpp +++ b/src/slave/containerizer/mesos/containerizer.cpp @@ -50,6 +50,10 @@ #include "hook/manager.hpp" +#ifdef __linux__ +#include "linux/memfd.hpp" +#endif // __linux__ + #include "module/manager.hpp" #include "slave/paths.hpp" @@ -565,6 +569,23 @@ Try<MesosContainerizer*> MesosContainerizer::create( _isolators.push_back(Owned<Isolator>(new MesosIsolator( Owned<MesosIsolatorProcess>(ioSwitchboard.get())))); + Option<int_fd> initMemFd; + +#ifdef __linux__ + // Clone the launcher binary in memory for security concerns. + Try<int_fd> memFd = memfd::cloneSealedFile( + path::join(flags.launcher_dir, MESOS_CONTAINERIZER)); + + if (memFd.isError()) { + return Error( + "Failed to clone a sealed file '" + + path::join(flags.launcher_dir, MESOS_CONTAINERIZER) + "' in memory: " + + memFd.error()); + } + + initMemFd = memFd.get(); +#endif // __linux__ + return new MesosContainerizer(Owned<MesosContainerizerProcess>( new MesosContainerizerProcess( flags, @@ -572,7 +593,8 @@ Try<MesosContainerizer*> MesosContainerizer::create( ioSwitchboard.get(), launcher, provisioner, - _isolators))); + _isolators, + initMemFd))); } @@ -1977,13 +1999,17 @@ Future<Containerizer::LaunchResult> MesosContainerizerProcess::_launch( launchFlagsEnvironment.end()); // Fork the child using launcher. + string initPath = initMemFd.isSome() + ? ("/proc/self/fd/" + stringify(initMemFd.get())) + : path::join(flags.launcher_dir, MESOS_CONTAINERIZER); + vector<string> argv(2); argv[0] = path::join(flags.launcher_dir, MESOS_CONTAINERIZER); argv[1] = MesosContainerizerLaunch::NAME; Try<pid_t> forked = launcher->fork( containerId, - argv[0], + initPath, argv, containerIO.get(), nullptr, diff --git a/src/slave/containerizer/mesos/containerizer.hpp b/src/slave/containerizer/mesos/containerizer.hpp index 22405e6..b0b4aff 100644 --- a/src/slave/containerizer/mesos/containerizer.hpp +++ b/src/slave/containerizer/mesos/containerizer.hpp @@ -139,16 +139,27 @@ public: IOSwitchboard* _ioSwitchboard, const process::Owned<Launcher>& _launcher, const process::Shared<Provisioner>& _provisioner, - const std::vector<process::Owned<mesos::slave::Isolator>>& _isolators) + const std::vector<process::Owned<mesos::slave::Isolator>>& _isolators, + const Option<int_fd>& _initMemFd) : ProcessBase(process::ID::generate("mesos-containerizer")), flags(_flags), fetcher(_fetcher), ioSwitchboard(_ioSwitchboard), launcher(_launcher), provisioner(_provisioner), - isolators(_isolators) {} + isolators(_isolators), + initMemFd(_initMemFd) {} - virtual ~MesosContainerizerProcess() {} + virtual ~MesosContainerizerProcess() + { + if (initMemFd.isSome()) { + Try<Nothing> close = os::close(initMemFd.get()); + if (close.isError()) { + LOG(WARNING) << "Failed to close memfd '" << stringify(initMemFd.get()) + << "': " << close.error(); + } + } + } virtual process::Future<Nothing> recover( const Option<state::SlaveState>& state); @@ -304,6 +315,7 @@ private: const process::Owned<Launcher> launcher; const process::Shared<Provisioner> provisioner; const std::vector<process::Owned<mesos::slave::Isolator>> isolators; + const Option<int_fd> initMemFd; struct Container {
