Repository: mesos
Updated Branches:
  refs/heads/master d61db9157 -> ff9ed0c83


Allowed whitelist additional devices in cgroups devices subsystem.

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


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

Branch: refs/heads/master
Commit: ff9ed0c831c347204d065c5f39e5c8bb86f38514
Parents: d61db91
Author: Zhongbo Tian <[email protected]>
Authored: Mon Apr 17 10:06:12 2017 +0800
Committer: Haosdent Huang <[email protected]>
Committed: Mon Apr 17 11:56:36 2017 +0800

----------------------------------------------------------------------
 docs/configuration.md                           |  21 ++++
 .../isolators/cgroups/subsystems/devices.cpp    | 111 ++++++++++++++++---
 .../isolators/cgroups/subsystems/devices.hpp    |   9 +-
 src/slave/flags.cpp                             |  16 +++
 src/slave/flags.hpp                             |   1 +
 5 files changed, 140 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/ff9ed0c8/docs/configuration.md
----------------------------------------------------------------------
diff --git a/docs/configuration.md b/docs/configuration.md
index 159f946..3c9aabc 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -1153,6 +1153,27 @@ effect only when the 
<code>--cgroups_net_cls_primary_handle</code> is set.
 </tr>
 <tr>
   <td>
+    --cgroups_whitelist_devices
+  </td>
+  <td>
+JSON array representing the devices that will be additionally
+whitelisted by cgroups devices subsystem. This will take effect
+only when <code>cgroups/devices</code> is set in <code>--isolation</code> flag.
+<p/>
+Example:
+<pre><code>[
+  {
+    "path": "/path/to/device",
+    "read_access": true,
+    "write_access": false,
+    "mknod_access": false
+  }
+]
+</code></pre>
+  </td>
+</tr>
+<tr>
+  <td>
     --cgroups_root=VALUE
   </td>
   <td>

http://git-wip-us.apache.org/repos/asf/mesos/blob/ff9ed0c8/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
----------------------------------------------------------------------
diff --git 
a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp 
b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
index 9b5cf83..d96e716 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
@@ -14,12 +14,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <sys/stat.h>
+
 #include <process/id.hpp>
 
 #include <stout/nothing.hpp>
 #include <stout/try.hpp>
-
-#include "linux/cgroups.hpp"
+#include <stout/os.hpp>
 
 #include "slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp"
 
@@ -30,6 +31,7 @@ using process::Future;
 using process::Owned;
 
 using std::string;
+using std::vector;
 
 namespace mesos {
 namespace internal {
@@ -63,15 +65,98 @@ Try<Owned<Subsystem>> DevicesSubsystem::create(
     const Flags& flags,
     const string& hierarchy)
 {
-  return Owned<Subsystem>(new DevicesSubsystem(flags, hierarchy));
+  vector<cgroups::devices::Entry> whitelistDeviceEntries;
+
+  foreach (const char* _entry, DEFAULT_WHITELIST_ENTRIES) {
+    Try<cgroups::devices::Entry> entry =
+      cgroups::devices::Entry::parse(_entry);
+
+    CHECK_SOME(entry);
+    whitelistDeviceEntries.push_back(entry.get());
+  }
+
+  if (flags.cgroups_whitelist_devices.isSome()) {
+    foreach (const JSON::Value& value,
+             flags.cgroups_whitelist_devices.get().values) {
+      if (!value.is<JSON::Object>()) {
+        return Error(
+            "Failed to parse whitelist devices '" +
+            stringify(flags.cgroups_whitelist_devices.get()) +
+            "' in flag --cgroups_whitelist_devices");
+      }
+
+      JSON::Object object = value.as<JSON::Object>();
+
+      Result<JSON::String> path = object.at<JSON::String>("path");
+      if (!path.isSome()) {
+        return Error("Malformed whitelist device entry '" +
+                     stringify(object) + "'");
+      }
+
+      Result<JSON::Boolean> _readAccess =
+        object.at<JSON::Boolean>("read_access");
+
+      Result<JSON::Boolean> _writeAccess =
+        object.at<JSON::Boolean>("write_access");
+
+      Result<JSON::Boolean> _mknodAccess =
+        object.at<JSON::Boolean>("mknod_access");
+
+      bool readAccess = (_readAccess.isSome() && _readAccess->value);
+      bool writeAccess = (_readAccess.isSome() && _readAccess->value);
+      bool mknodAccess = (_readAccess.isSome() && _readAccess->value);
+
+      if (!(readAccess || writeAccess || mknodAccess)) {
+        return Error("Could not whitelist device '" + path->value
+                     + "' without any access privileges");
+      }
+
+      Try<dev_t> device = os::stat::rdev(path->value);
+      if (device.isError()) {
+        return Error("Failed to obtain device ID for '" + path->value +
+                     "': " + device.error());
+      }
+
+      Try<mode_t> mode = os::stat::mode(path->value);
+      if (mode.isError()) {
+        return Error("Failed to obtain device mode for '" + path->value +
+                     "': " + mode.error());
+      }
+
+      Entry::Selector::Type type;
+      if (S_ISBLK(mode.get())) {
+          type = Entry::Selector::Type::BLOCK;
+      } else if (S_ISCHR(mode.get())) {
+          type = Entry::Selector::Type::CHARACTER;
+      } else {
+          return Error("Failed to determine device type for '" + path->value +
+                       "'");
+      }
+
+      cgroups::devices::Entry entry;
+      entry.selector.type = type;
+      entry.selector.major = major(device.get());
+      entry.selector.minor = minor(device.get());
+      entry.access.read = readAccess;
+      entry.access.write = writeAccess;
+      entry.access.mknod = mknodAccess;
+
+      whitelistDeviceEntries.push_back(entry);
+    }
+  }
+
+  return Owned<Subsystem>(
+      new DevicesSubsystem(flags, hierarchy, whitelistDeviceEntries));
 }
 
 
 DevicesSubsystem::DevicesSubsystem(
     const Flags& _flags,
-    const string& _hierarchy)
+    const string& _hierarchy,
+    const vector<cgroups::devices::Entry>& _whitelistDeviceEntries)
   : ProcessBase(process::ID::generate("cgroups-devices-subsystem")),
-    Subsystem(_flags, _hierarchy) {}
+    Subsystem(_flags, _hierarchy),
+    whitelistDeviceEntries(_whitelistDeviceEntries) {}
 
 
 Future<Nothing> DevicesSubsystem::recover(
@@ -127,20 +212,12 @@ Future<Nothing> DevicesSubsystem::prepare(
     return Failure("Failed to deny all devices: " + deny.error());
   }
 
-  foreach (const char* _entry, DEFAULT_WHITELIST_ENTRIES) {
-    Try<cgroups::devices::Entry> entry =
-      cgroups::devices::Entry::parse(_entry);
-
-    CHECK_SOME(entry);
-
-    Try<Nothing> allow = cgroups::devices::allow(
-        hierarchy,
-        cgroup,
-        entry.get());
+  foreach (const cgroups::devices::Entry& entry, whitelistDeviceEntries) {
+    Try<Nothing> allow = cgroups::devices::allow(hierarchy, cgroup, entry);
 
     if (allow.isError()) {
-      return Failure("Failed to whitelist default device "
-                     "'" + stringify(entry.get()) + "': " + allow.error());
+      return Failure("Failed to whitelist device "
+                     "'" + stringify(entry) + "': " + allow.error());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/ff9ed0c8/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
----------------------------------------------------------------------
diff --git 
a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp 
b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
index ca27271..4ab224e 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
@@ -18,12 +18,15 @@
 #define __CGROUPS_ISOLATOR_SUBSYSTEMS_DEVICES_HPP__
 
 #include <string>
+#include <vector>
 
 #include <process/owned.hpp>
 
 #include <stout/hashset.hpp>
 #include <stout/try.hpp>
 
+#include "linux/cgroups.hpp"
+
 #include "slave/flags.hpp"
 
 #include "slave/containerizer/mesos/isolators/cgroups/constants.hpp"
@@ -63,9 +66,13 @@ public:
       const std::string& cgroup);
 
 private:
-  DevicesSubsystem(const Flags& flags, const std::string& hierarchy);
+  DevicesSubsystem(
+      const Flags& flags,
+      const std::string& hierarchy,
+      const std::vector<cgroups::devices::Entry>& whitelistDeviceEntries);
 
   hashset<ContainerID> containerIds;
+  std::vector<cgroups::devices::Entry> whitelistDeviceEntries;
 };
 
 } // namespace slave {

http://git-wip-us.apache.org/repos/asf/mesos/blob/ff9ed0c8/src/slave/flags.cpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.cpp b/src/slave/flags.cpp
index c50e43c..f22837c 100644
--- a/src/slave/flags.cpp
+++ b/src/slave/flags.cpp
@@ -454,6 +454,22 @@ mesos::internal::slave::Flags::Flags()
       "handles that can be used with the primary handle. This will take\n"
       "effect only when the `--cgroups_net_cls_primary_handle is set.");
 
+  add(&Flags::cgroups_whitelist_devices,
+      "cgroups_whitelist_devices",
+      "JSON array representing the devices that will be additionally\n"
+      "whitelisted by cgroups devices subsystem. This will take effect\n"
+      "only when `cgroups/devices` is set in `--isolation` flag.\n"
+      "Example:\n"
+      "[\n"
+      "    {\n"
+      "        \"path\": \"/path/to/device\",\n"
+      "        \"read_access\": true,\n"
+      "        \"write_access\": false,\n"
+      "        \"mknod_access\": false\n"
+      "    }\n"
+      "]\n"
+      );
+
   add(&Flags::agent_subsystems,
       "agent_subsystems",
       flags::DeprecatedName("slave_subsystems"),

http://git-wip-us.apache.org/repos/asf/mesos/blob/ff9ed0c8/src/slave/flags.hpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.hpp b/src/slave/flags.hpp
index c7a4604..38c05af 100644
--- a/src/slave/flags.hpp
+++ b/src/slave/flags.hpp
@@ -99,6 +99,7 @@ public:
   bool cgroups_cpu_enable_pids_and_tids_count;
   Option<std::string> cgroups_net_cls_primary_handle;
   Option<std::string> cgroups_net_cls_secondary_handles;
+  Option<JSON::Array> cgroups_whitelist_devices;
   Option<std::string> agent_subsystems;
   Option<std::vector<unsigned int>> nvidia_gpu_devices;
   Option<std::string> perf_events;

Reply via email to