[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mesos-commits
Subject:    (mesos) branch master updated: [cgroups2] Add device controller tests.
From:       bmahler () apache ! org
Date:       2024-03-29 0:17:52
Message-ID: 171167147288.2437998.6573385529931829482 () gitbox2-he-fi ! apache ! org
[Download RAW message or body]

This is an automated email from the ASF dual-hosted git repository.

bmahler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git


The following commit(s) were added to refs/heads/master by this push:
     new b58bd7c02 [cgroups2] Add device controller tests.
b58bd7c02 is described below

commit b58bd7c027d46e24b94d953a7f8e0a93d37b2986
Author: Devin Leamy <dleamy@twitter.com>
AuthorDate: Thu Mar 28 19:57:39 2024 -0400

    [cgroups2] Add device controller tests.
    
    Added tests for the ebpf programs created by the device controller.
    
    This closes #538
---
 src/tests/containerizer/cgroups2_tests.cpp | 153 +++++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/src/tests/containerizer/cgroups2_tests.cpp b/src/tests/containerizer/cgroups2_tests.cpp
index db541a5ca..38f062ffb 100644
--- a/src/tests/containerizer/cgroups2_tests.cpp
+++ b/src/tests/containerizer/cgroups2_tests.cpp
@@ -16,23 +16,33 @@
 
 #include <set>
 #include <string>
+#include <tuple>
+#include <utility>
 #include <vector>
 
 #include <process/reap.hpp>
+#include <process/gmock.hpp>
 #include <process/gtest.hpp>
 
 #include <stout/exit.hpp>
 #include <stout/foreach.hpp>
+#include <stout/gtest.hpp>
+#include <stout/os.hpp>
 #include <stout/set.hpp>
 #include <stout/tests/utils.hpp>
 #include <stout/try.hpp>
 
 #include "linux/cgroups2.hpp"
+#include "linux/ebpf.hpp"
 
+using std::pair;
 using std::set;
 using std::string;
+using std::tuple;
 using std::vector;
 
+namespace devices = cgroups2::devices;
+
 namespace mesos {
 namespace internal {
 namespace tests {
@@ -210,6 +220,149 @@ TEST_F(Cgroups2Test, ROOT_CGROUPS2_EnableAndDisable)
   EXPECT_EQ(0u, enabled->count("cpu"));
 }
 
+// Arguments for os::open(). Combination of a path and an access type.
+typedef pair<string, int> OpenArgs;
+
+using DeviceControllerTestParams = tuple<
+    vector<devices::Entry>,
+    vector<devices::Entry>,
+    vector<OpenArgs>,
+    vector<OpenArgs>>;
+
+class DeviceControllerTestFixture :
+    public Cgroups2Test,
+    public ::testing::WithParamInterface<DeviceControllerTestParams> {};
+
+
+TEST_P(DeviceControllerTestFixture, ROOT_CGROUPS2_DeviceController)
+{
+  const string& cgroup = TEST_CGROUP;
+
+  auto params = GetParam();
+  const vector<devices::Entry>& allow = std::get<0>(params);
+  const vector<devices::Entry>& deny = std::get<1>(params);
+  const vector<OpenArgs>& allowed_accesses = std::get<2>(params);
+  const vector<OpenArgs>& blocked_accesses = std::get<3>(params);
+
+  ASSERT_SOME(cgroups2::create(cgroup));
+  string path = cgroups2::path(cgroup);
+
+  Try<vector<uint32_t>> attached = ebpf::cgroups2::attached(path);
+  ASSERT_SOME(attached);
+  ASSERT_EQ(0u, attached->size());
+
+  ASSERT_SOME(devices::configure(cgroup, allow, deny));
+  attached = ebpf::cgroups2::attached(path);
+  ASSERT_SOME(attached);
+  ASSERT_EQ(1u, attached->size());
+
+  pid_t pid = ::fork();
+  ASSERT_NE(-1, pid);
+
+  if (pid == 0) {
+    // Move the child process into the newly created cgroup.
+    Try<Nothing> assign = cgroups2::assign(cgroup, ::getpid());
+    if (assign.isError()) {
+      SAFE_EXIT(EXIT_FAILURE, "Failed to assign child process to cgroup");
+    }
+
+    // Check that we can only do the "allowed_accesses".
+    foreach(const OpenArgs& args, allowed_accesses) {
+      if (os::open(args.first, args.second).isError()) {
+        SAFE_EXIT(EXIT_FAILURE, "Expected allowed read to succeed");
+      }
+    }
+    foreach(const OpenArgs& args, blocked_accesses) {
+      if (os::open(args.first, args.second).isSome()) {
+        SAFE_EXIT(EXIT_FAILURE, "Expected blocked read to fail");
+      }
+    }
+
+    ASSERT_SOME(ebpf::cgroups2::detach(path, attached->at(0)));
+
+    // Check that we can do both the "allowed_accesses" and "blocked_accesses".
+    foreach(const OpenArgs& args, allowed_accesses) {
+      if (os::open(args.first, args.second).isError()) {
+        SAFE_EXIT(EXIT_FAILURE, "Expected successful read after detaching"
+          " device controller program");
+      }
+    }
+    foreach(const OpenArgs& args, blocked_accesses) {
+      if (os::open(args.first, args.second).isError()) {
+        SAFE_EXIT(EXIT_FAILURE, "Expected successful read after detaching"
+          " device controller program");
+      }
+    }
+
+    ::_exit(EXIT_SUCCESS);
+  }
+
+  AWAIT_EXPECT_WEXITSTATUS_EQ(EXIT_SUCCESS, process::reap(pid));
+}
+
+
+INSTANTIATE_TEST_CASE_P(
+    DeviceControllerTestParams,
+    DeviceControllerTestFixture,
+    ::testing::Values<DeviceControllerTestParams>(
+        // Acceses are blocked by default if no entries are configured.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{},
+          vector<devices::Entry>{},
+          vector<OpenArgs>{},
+          vector<OpenArgs>{{os::DEV_NULL, O_RDWR}, {os::DEV_NULL, O_RDWR}}
+        },
+        // Deny access to /dev/null.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{},
+          vector<devices::Entry>{*devices::Entry::parse("c 1:3 rwm")},
+          vector<OpenArgs>{},
+          vector<OpenArgs>{{os::DEV_NULL, O_RDWR}}
+        },
+        // Allow access to /dev/null.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{*devices::Entry::parse("c 1:3 rwm")},
+          vector<devices::Entry>{},
+          vector<OpenArgs>{{os::DEV_NULL, O_RDWR}},
+          vector<OpenArgs>{}
+        },
+        // Allow read-only access to /dev/null.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{*devices::Entry::parse("c 1:3 r")},
+          vector<devices::Entry>{},
+          vector<OpenArgs>{{os::DEV_NULL, O_RDONLY}},
+          vector<OpenArgs>{{os::DEV_NULL, O_RDWR}}
+        },
+        // Allow write-only access to /dev/null.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{*devices::Entry::parse("c 1:3 w")},
+          vector<devices::Entry>{},
+            // write-only allowed
+          vector<OpenArgs>{{os::DEV_NULL, O_WRONLY}},
+            // read is blocked
+          vector<OpenArgs>{{os::DEV_NULL, O_RDWR}, {os::DEV_NULL, O_RDONLY}}
+        },
+        // Access to /dev/null is denied because the allowed access is to
+        // a different device type with the same major:minor numbers.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{*devices::Entry::parse("b 1:3 rwm")},
+          vector<devices::Entry>{},
+          vector<OpenArgs>{},
+            // /dev/null is blocked
+          vector<OpenArgs>{{os::DEV_NULL, O_RDWR}, {os::DEV_NULL, O_RDONLY}}
+        },
+        // Allow access to all devices.
+        DeviceControllerTestParams{
+          vector<devices::Entry>{*devices::Entry::parse("a *:* rwm")},
+          vector<devices::Entry>{},
+          vector<OpenArgs>{
+            {os::DEV_NULL, O_WRONLY},
+            {os::DEV_NULL, O_RDWR},
+            {os::DEV_NULL, O_RDONLY}},
+          vector<OpenArgs>{},
+        }
+      ));
+
 } // namespace tests {
 
 } // namespace internal {

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic