You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/09/10 00:45:05 UTC

mesos git commit: Introduced linux capabilities support for mesos containerizer.

Repository: mesos
Updated Branches:
  refs/heads/master 02f13c9aa -> 8f7bd95ed


Introduced linux capabilities support for mesos containerizer.

This change introduces linux capability based security for unified
containerizer. A new agent flag `allowed_capabilities` has been
introduced to override the default capabilities of the user or the
capabilities requested by the user.

This feature is only available on linux.

Review: https://reviews.apache.org/r/50270/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/8f7bd95e
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/8f7bd95e
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/8f7bd95e

Branch: refs/heads/master
Commit: 8f7bd95ed3f4111c327ff4a376388cb961f207d9
Parents: 02f13c9
Author: Benjamin Bannier <be...@mesosphere.io>
Authored: Fri Sep 9 16:38:48 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Sep 9 17:29:49 2016 -0700

----------------------------------------------------------------------
 src/slave/containerizer/mesos/launch.cpp | 81 +++++++++++++++++++++++++++
 src/slave/containerizer/mesos/launch.hpp |  1 +
 src/slave/flags.cpp                      | 28 +++++++++
 src/slave/flags.hpp                      |  1 +
 4 files changed, 111 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/8f7bd95e/src/slave/containerizer/mesos/launch.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.cpp b/src/slave/containerizer/mesos/launch.cpp
index 13b65d8..b8ad27e 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -30,6 +30,7 @@
 #include <stout/unreachable.hpp>
 
 #ifdef __linux__
+#include "linux/capabilities.hpp"
 #include "linux/fs.hpp"
 #include "linux/ns.hpp"
 #endif
@@ -46,6 +47,12 @@ using std::vector;
 
 using process::Subprocess;
 
+#ifdef __linux__
+using mesos::internal::capabilities::Capabilities;
+using mesos::internal::capabilities::Capability;
+using mesos::internal::capabilities::ProcessCapabilities;
+#endif // __linux__
+
 namespace mesos {
 namespace internal {
 namespace slave {
@@ -101,6 +108,10 @@ MesosContainerizerLaunch::Flags::Flags()
       "unshare_namespace_mnt",
       "Whether to launch the command in a new mount namespace.",
       false);
+
+  add(&capabilities,
+      "capabilities",
+      "Capabilities of the command can use.");
 #endif // __linux__
 }
 
@@ -303,6 +314,30 @@ int MesosContainerizerLaunch::execute()
   }
 #endif // __WINDOWS__
 
+#ifdef __linux__
+  // Initialize capabilities support if necessary.
+  Try<Capabilities> capabilitiesManager = Error("Not initialized");
+
+  if (flags.capabilities.isSome()) {
+    capabilitiesManager = Capabilities::create();
+    if (capabilitiesManager.isError()) {
+      cerr << "Failed to initialize capabilities support: "
+           << capabilitiesManager.error() << endl;
+      return EXIT_FAILURE;
+    }
+
+    // Prevent clearing of capabilities on `setuid`.
+    if (uid.isSome()) {
+      Try<Nothing> keepCaps = capabilitiesManager->setKeepCaps();
+      if (keepCaps.isError()) {
+        cerr << "Failed to set process control for keeping capabilities "
+             << "on potential uid change: " << keepCaps.error() << endl;
+        return EXIT_FAILURE;
+      }
+    }
+  }
+#endif // __linux__
+
 #ifdef __WINDOWS__
   // Not supported on Windows.
   const Option<std::string> rootfs = None();
@@ -370,6 +405,52 @@ int MesosContainerizerLaunch::execute()
   }
 #endif // __WINDOWS__
 
+#ifdef __linux__
+  if (flags.capabilities.isSome()) {
+    Try<CapabilityInfo> requestedCapabilities =
+      ::protobuf::parse<CapabilityInfo>(flags.capabilities.get());
+
+    if (requestedCapabilities.isError()) {
+      cerr << "Failed to parse capabilities: "
+           << requestedCapabilities.error() << endl;
+      return EXIT_FAILURE;
+    }
+
+    Try<ProcessCapabilities> capabilities = capabilitiesManager->get();
+    if (capabilities.isError()) {
+      cerr << "Failed to get capabilities for the current process: "
+           << capabilities.error() << endl;
+      return EXIT_FAILURE;
+    }
+
+    // After 'setuid', 'effective' set is cleared. Since `SETPCAP` is
+    // required in the `effective` set of a process to change the
+    // bounding set, we need to restore it first.
+    capabilities->add(capabilities::EFFECTIVE, capabilities::SETPCAP);
+
+    Try<Nothing> setPcap = capabilitiesManager->set(capabilities.get());
+    if (setPcap.isError()) {
+      cerr << "Failed to add SETPCAP to the effective set: "
+           << setPcap.error() << endl;
+      return EXIT_FAILURE;
+    }
+
+    // Set up requested capabilities.
+    Set<Capability> target = capabilities::convert(requestedCapabilities.get());
+
+    capabilities->set(capabilities::EFFECTIVE, target);
+    capabilities->set(capabilities::PERMITTED, target);
+    capabilities->set(capabilities::INHERITABLE, target);
+    capabilities->set(capabilities::BOUNDING, target);
+
+    Try<Nothing> set = capabilitiesManager->set(capabilities.get());
+    if (set.isError()) {
+      cerr << "Failed to set process capabilities: " << set.error() << endl;
+      return EXIT_FAILURE;
+    }
+  }
+#endif // __linux__
+
   if (flags.working_directory.isSome()) {
     Try<Nothing> chdir = os::chdir(flags.working_directory.get());
     if (chdir.isError()) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/8f7bd95e/src/slave/containerizer/mesos/launch.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.hpp b/src/slave/containerizer/mesos/launch.hpp
index 0e86da9..859990c 100644
--- a/src/slave/containerizer/mesos/launch.hpp
+++ b/src/slave/containerizer/mesos/launch.hpp
@@ -45,6 +45,7 @@ public:
     Option<JSON::Array> pre_exec_commands;
 #ifdef __linux__
     bool unshare_namespace_mnt;
+    Option<JSON::Object> capabilities;
 #endif // __linux__
   };
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/8f7bd95e/src/slave/flags.cpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.cpp b/src/slave/flags.cpp
index 0f2be17..f6cd6f7 100644
--- a/src/slave/flags.cpp
+++ b/src/slave/flags.cpp
@@ -452,6 +452,34 @@ mesos::internal::slave::Flags::Flags()
       "systemd_runtime_directory",
       "The path to the systemd system run time directory\n",
       "/run/systemd/system");
+
+  add(&Flags::allowed_capabilities,
+      "allowed_capabilities",
+      "JSON representation of system capabilities that the operator will\n"
+      "allow for a task that will be run in a container launched by the\n"
+      "containerizer (currently only supported in MesosContainerizer).\n"
+      "This set overrides the default capabilities for the user and the\n"
+      "capabilities requested by the framework.\n"
+      "\n"
+      "The net capability for a task running in the container would be:\n"
+      "   ((F & A) & U)\n"
+      "   where F = capabilities requested by the framework.\n"
+      "         U = permitted capabilities for the agent process.\n"
+      "         A = allowed capabilities specified by this flag.\n"
+      "\n"
+      "To set capabilities the agent should have the `SETPCAP` capability.\n"
+      "\n"
+      "This flag is effective iff `capabilities` isolation is enabled.\n"
+      "When `capabilities` isolation is enabled, the absense of this flag\n"
+      "would imply that the operator would allow ALL capabilities.\n"
+      "\n"
+      "Example:\n"
+      "{\n"
+      "   \"capabilities\": [\n"
+      "       \"NET_RAW\",\n"
+      "       \"SYS_ADMIN\"\n"
+      "     ]\n"
+      "}");
 #endif
 
   add(&Flags::firewall_rules,

http://git-wip-us.apache.org/repos/asf/mesos/blob/8f7bd95e/src/slave/flags.hpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.hpp b/src/slave/flags.hpp
index 1a00666..897f3f8 100644
--- a/src/slave/flags.hpp
+++ b/src/slave/flags.hpp
@@ -100,6 +100,7 @@ public:
   bool revocable_cpu_low_priority;
   bool systemd_enable_support;
   std::string systemd_runtime_directory;
+  Option<CapabilityInfo> allowed_capabilities;
 #endif
   Option<Firewall> firewall_rules;
   Option<Path> credential;