blob: b9e8e6eeed82db89340ca404a567f496a195d3ed [file] [log] [blame]
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -07001/* Copyright 2016 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include <errno.h>
7
Luis Hector Chavezfd81db42018-01-31 12:18:39 -08008#include <fcntl.h>
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -07009#include <sys/stat.h>
10#include <sys/types.h>
11#include <unistd.h>
12
13#include <base/files/file_path.h>
14#include <base/files/file_util.h>
15#include <base/files/scoped_temp_dir.h>
16#include <base/logging.h>
17#include <base/strings/string_split.h>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070018#include <gtest/gtest.h>
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070019
20#include "libcontainer/cgroup.h"
21
Luis Hector Chavez58725a82017-09-19 21:14:17 -070022namespace libcontainer {
23
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070024namespace {
25
26constexpr char kCgroupName[] = "testcg";
27constexpr char kCgroupParentName[] = "testparentcg";
28
29bool CreateFile(const base::FilePath& path) {
30 return base::WriteFile(path, "", 0) == 0;
31}
32
33bool FileHasString(const base::FilePath& path, const std::string& expected) {
34 std::string contents;
35 if (!base::ReadFileToString(path, &contents))
36 return false;
37
38 return contents.find(expected) != std::string::npos;
39}
40
41bool FileHasLine(const base::FilePath& path, const std::string& expected) {
42 std::string contents;
43 if (!base::ReadFileToString(path, &contents))
44 return false;
45
46 for (const auto& line : base::SplitString(
47 contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
48 if (line == expected)
49 return true;
50 }
51 return false;
52}
53
54} // namespace
55
Luis Hector Chavez58725a82017-09-19 21:14:17 -070056TEST(CgroupTest, CgroupNewWithParent) {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070057 base::ScopedTempDir temp_dir;
58 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Eric Carusobf34ef72018-01-22 15:44:55 -080059 base::FilePath cgroup_root = temp_dir.GetPath();
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070060
61 for (const char* subsystem :
62 {"cpu", "cpuacct", "cpuset", "devices", "freezer", "schedtune"}) {
63 base::FilePath path = cgroup_root.Append(subsystem);
64 EXPECT_EQ(0, mkdir(path.value().c_str(), S_IRWXU | S_IRWXG));
65 path = path.Append(kCgroupParentName);
66 EXPECT_EQ(0, mkdir(path.value().c_str(), S_IRWXU | S_IRWXG));
67 }
68
69 ASSERT_TRUE(base::WriteFile(
70 cgroup_root.Append("cpuset").Append(kCgroupParentName).Append("cpus"),
Tom Hughes25f969a2020-08-27 15:57:27 -070071 "0-3", 3));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070072 ASSERT_TRUE(base::WriteFile(
73 cgroup_root.Append("cpuset").Append(kCgroupParentName).Append("mems"),
Tom Hughes25f969a2020-08-27 15:57:27 -070074 "0", 1));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070075
Tom Hughes25f969a2020-08-27 15:57:27 -070076 std::unique_ptr<libcontainer::Cgroup> ccg = libcontainer::Cgroup::Create(
77 kCgroupName, cgroup_root, base::FilePath(kCgroupParentName), getuid(),
78 getgid());
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070079 ASSERT_NE(nullptr, ccg.get());
80
81 EXPECT_TRUE(base::DirectoryExists(
82 cgroup_root.Append("cpu").Append(kCgroupParentName).Append(kCgroupName)));
83 EXPECT_TRUE(base::DirectoryExists(cgroup_root.Append("cpuacct")
84 .Append(kCgroupParentName)
85 .Append(kCgroupName)));
86 EXPECT_TRUE(base::DirectoryExists(cgroup_root.Append("cpuset")
87 .Append(kCgroupParentName)
88 .Append(kCgroupName)));
89 EXPECT_TRUE(base::DirectoryExists(cgroup_root.Append("devices")
90 .Append(kCgroupParentName)
91 .Append(kCgroupName)));
92 EXPECT_TRUE(base::DirectoryExists(cgroup_root.Append("freezer")
93 .Append(kCgroupParentName)
94 .Append(kCgroupName)));
95 EXPECT_TRUE(base::DirectoryExists(cgroup_root.Append("schedtune")
96 .Append(kCgroupParentName)
97 .Append(kCgroupName)));
98
99 EXPECT_TRUE(temp_dir.Delete());
100}
101
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700102class BasicCgroupManipulationTest : public ::testing::Test {
103 public:
104 BasicCgroupManipulationTest() = default;
105 ~BasicCgroupManipulationTest() override = default;
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700106
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700107 void SetUp() override {
108 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700109
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700110 base::FilePath cgroup_root;
Satoru Takabayashicf730fb2018-08-03 16:42:36 +0900111 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_.GetPath(), "cgtest",
112 &cgroup_root));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700113
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700114 for (const char* subsystem :
115 {"cpu", "cpuacct", "cpuset", "devices", "freezer", "schedtune"}) {
116 base::FilePath path = cgroup_root.Append(subsystem);
117 ASSERT_EQ(0, mkdir(path.value().c_str(), S_IRWXU | S_IRWXG));
118 }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700119
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700120 ASSERT_TRUE(base::WriteFile(cgroup_root.Append("cpuset/cpus"), "0-3", 3));
121 ASSERT_TRUE(base::WriteFile(cgroup_root.Append("cpuset/mems"), "0", 1));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700122
Tom Hughes25f969a2020-08-27 15:57:27 -0700123 ccg_ = libcontainer::Cgroup::Create(kCgroupName, cgroup_root,
124 base::FilePath(), 0, 0);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700125 ASSERT_NE(nullptr, ccg_.get());
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700126
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700127 cpu_cg_ = cgroup_root.Append("cpu").Append(kCgroupName);
128 cpuacct_cg_ = cgroup_root.Append("cpuacct").Append(kCgroupName);
129 cpuset_cg_ = cgroup_root.Append("cpuset").Append(kCgroupName);
130 devices_cg_ = cgroup_root.Append("devices").Append(kCgroupName);
131 freezer_cg_ = cgroup_root.Append("freezer").Append(kCgroupName);
132 schedtune_cg_ = cgroup_root.Append("schedtune").Append(kCgroupName);
133
134 ASSERT_TRUE(base::DirectoryExists(cpu_cg_));
135 ASSERT_TRUE(base::DirectoryExists(cpuacct_cg_));
136 ASSERT_TRUE(base::DirectoryExists(cpuset_cg_));
137 ASSERT_TRUE(base::DirectoryExists(devices_cg_));
138 ASSERT_TRUE(base::DirectoryExists(freezer_cg_));
139 ASSERT_TRUE(base::DirectoryExists(schedtune_cg_));
140
141 ASSERT_TRUE(CreateFile(cpu_cg_.Append("tasks")));
142 ASSERT_TRUE(CreateFile(cpu_cg_.Append("cpu.shares")));
143 ASSERT_TRUE(CreateFile(cpu_cg_.Append("cpu.cfs_quota_us")));
144 ASSERT_TRUE(CreateFile(cpu_cg_.Append("cpu.cfs_period_us")));
145 ASSERT_TRUE(CreateFile(cpu_cg_.Append("cpu.rt_runtime_us")));
146 ASSERT_TRUE(CreateFile(cpu_cg_.Append("cpu.rt_period_us")));
147 ASSERT_TRUE(CreateFile(cpuacct_cg_.Append("tasks")));
148 ASSERT_TRUE(CreateFile(cpuset_cg_.Append("tasks")));
149 ASSERT_TRUE(CreateFile(devices_cg_.Append("tasks")));
150 ASSERT_TRUE(CreateFile(devices_cg_.Append("devices.allow")));
151 ASSERT_TRUE(CreateFile(devices_cg_.Append("devices.deny")));
152 ASSERT_TRUE(CreateFile(freezer_cg_.Append("tasks")));
153 ASSERT_TRUE(CreateFile(freezer_cg_.Append("freezer.state")));
154 ASSERT_TRUE(CreateFile(schedtune_cg_.Append("tasks")));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700155 }
156
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700157 void TearDown() override {
158 ccg_.reset();
159 ASSERT_TRUE(temp_dir_.Delete());
160 }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700161
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700162 protected:
163 std::unique_ptr<libcontainer::Cgroup> ccg_;
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700164
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700165 base::FilePath cpu_cg_;
166 base::FilePath cpuacct_cg_;
167 base::FilePath cpuset_cg_;
168 base::FilePath devices_cg_;
169 base::FilePath freezer_cg_;
170 base::FilePath schedtune_cg_;
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700171
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700172 base::ScopedTempDir temp_dir_;
173};
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700174
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700175TEST_F(BasicCgroupManipulationTest, freeze) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700176 EXPECT_TRUE(ccg_->Freeze());
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700177 EXPECT_TRUE(FileHasString(freezer_cg_.Append("freezer.state"), "FROZEN"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700178}
179
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700180TEST_F(BasicCgroupManipulationTest, thaw) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700181 EXPECT_TRUE(ccg_->Thaw());
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700182 EXPECT_TRUE(FileHasString(freezer_cg_.Append("freezer.state"), "THAWED"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700183}
184
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700185TEST_F(BasicCgroupManipulationTest, default_all_devs_disallow) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700186 ASSERT_TRUE(ccg_->DenyAllDevices());
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700187 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.deny"), "a"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700188}
189
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700190TEST_F(BasicCgroupManipulationTest, add_device_invalid_type) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700191 EXPECT_FALSE(ccg_->AddDevice(1, 14, 3, 1, 1, 0, 'x'));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700192}
193
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700194TEST_F(BasicCgroupManipulationTest, add_device_no_perms) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700195 EXPECT_FALSE(ccg_->AddDevice(1, 14, 3, 0, 0, 0, 'c'));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700196}
197
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700198TEST_F(BasicCgroupManipulationTest, add_device_rw) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700199 EXPECT_TRUE(ccg_->AddDevice(1, 14, 3, 1, 1, 0, 'c'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700200 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "c 14:3 rw"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700201}
202
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700203TEST_F(BasicCgroupManipulationTest, add_device_rwm) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700204 EXPECT_TRUE(ccg_->AddDevice(1, 14, 3, 1, 1, 1, 'c'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700205 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "c 14:3 rwm"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700206}
207
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700208TEST_F(BasicCgroupManipulationTest, add_device_ro) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700209 EXPECT_TRUE(ccg_->AddDevice(1, 14, 3, 1, 0, 0, 'c'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700210 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "c 14:3 r"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700211}
212
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700213TEST_F(BasicCgroupManipulationTest, add_device_wo) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700214 EXPECT_TRUE(ccg_->AddDevice(1, 14, 3, 0, 1, 0, 'c'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700215 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "c 14:3 w"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700216}
217
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700218TEST_F(BasicCgroupManipulationTest, add_device_major_wide) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700219 EXPECT_TRUE(ccg_->AddDevice(1, 14, -1, 0, 1, 0, 'c'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700220 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "c 14:* w"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700221}
222
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700223TEST_F(BasicCgroupManipulationTest, add_device_major_minor_wildcard) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700224 EXPECT_TRUE(ccg_->AddDevice(1, -1, -1, 0, 1, 0, 'c'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700225 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "c *:* w"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700226}
227
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700228TEST_F(BasicCgroupManipulationTest, add_device_deny_all) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700229 EXPECT_TRUE(ccg_->AddDevice(0, -1, -1, 1, 1, 1, 'a'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700230 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.deny"), "a *:* rwm"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700231}
232
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700233TEST_F(BasicCgroupManipulationTest, add_device_block) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700234 EXPECT_TRUE(ccg_->AddDevice(1, 14, 3, 1, 1, 0, 'b'));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700235 EXPECT_TRUE(FileHasLine(devices_cg_.Append("devices.allow"), "b 14:3 rw"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700236}
237
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700238TEST_F(BasicCgroupManipulationTest, set_cpu_shares) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700239 EXPECT_TRUE(ccg_->SetCpuShares(500));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700240 EXPECT_TRUE(FileHasString(cpu_cg_.Append("cpu.shares"), "500"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700241}
242
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700243TEST_F(BasicCgroupManipulationTest, set_cpu_quota) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700244 EXPECT_TRUE(ccg_->SetCpuQuota(200000));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700245 EXPECT_TRUE(FileHasString(cpu_cg_.Append("cpu.cfs_quota_us"), "200000"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700246}
247
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700248TEST_F(BasicCgroupManipulationTest, set_cpu_period) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700249 EXPECT_TRUE(ccg_->SetCpuPeriod(800000));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700250 EXPECT_TRUE(FileHasString(cpu_cg_.Append("cpu.cfs_period_us"), "800000"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700251}
252
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700253TEST_F(BasicCgroupManipulationTest, set_cpu_rt_runtime) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700254 EXPECT_TRUE(ccg_->SetCpuRtRuntime(100000));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700255 EXPECT_TRUE(FileHasString(cpu_cg_.Append("cpu.rt_runtime_us"), "100000"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700256}
257
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700258TEST_F(BasicCgroupManipulationTest, set_cpu_rt_period) {
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700259 EXPECT_TRUE(ccg_->SetCpuRtPeriod(500000));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700260 EXPECT_TRUE(FileHasString(cpu_cg_.Append("cpu.rt_period_us"), "500000"));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700261}
262
Luis Hector Chavezfd81db42018-01-31 12:18:39 -0800263TEST_F(BasicCgroupManipulationTest, OpenCgroupFileRefusesToWriteToSymlink) {
264 base::FilePath cpu_rt_period_us_path = cpu_cg_.Append("cpu.rt_period_us");
265 base::FilePath target_path = cpu_cg_.Append("symlink_target");
hscham53cf73a2020-11-30 15:58:42 +0900266 ASSERT_TRUE(base::DeleteFile(cpu_rt_period_us_path));
Luis Hector Chavezfd81db42018-01-31 12:18:39 -0800267 ASSERT_TRUE(base::CreateSymbolicLink(target_path, cpu_rt_period_us_path));
268
269 // This should fail since we are trying to write to a symlink.
270 EXPECT_FALSE(ccg_->SetCpuRtPeriod(500000));
271}
272
273TEST_F(BasicCgroupManipulationTest, OpenCgroupFileRefusesToWriteToNonOpenFIFO) {
274 base::FilePath cpu_rt_period_us_path = cpu_cg_.Append("cpu.rt_period_us");
hscham53cf73a2020-11-30 15:58:42 +0900275 ASSERT_TRUE(base::DeleteFile(cpu_rt_period_us_path));
Luis Hector Chavezfd81db42018-01-31 12:18:39 -0800276 ASSERT_NE(mkfifo(cpu_rt_period_us_path.value().c_str(), 0664), -1);
277
278 // This should fail since we are trying to write to a FIFO.
279 EXPECT_FALSE(ccg_->SetCpuRtPeriod(500000));
280}
281
282TEST_F(BasicCgroupManipulationTest, OpenCgroupFileRefusesToWriteToOpenFIFO) {
283 base::FilePath cpu_rt_period_us_path = cpu_cg_.Append("cpu.rt_period_us");
hscham53cf73a2020-11-30 15:58:42 +0900284 ASSERT_TRUE(base::DeleteFile(cpu_rt_period_us_path));
Luis Hector Chavezfd81db42018-01-31 12:18:39 -0800285 ASSERT_NE(mkfifo(cpu_rt_period_us_path.value().c_str(), 0664), -1);
286 base::ScopedFD fd(
287 open(cpu_rt_period_us_path.value().c_str(), O_RDONLY | O_NONBLOCK));
288 ASSERT_TRUE(fd.is_valid());
289
290 // This should fail since we are trying to write to a FIFO.
291 EXPECT_FALSE(ccg_->SetCpuRtPeriod(500000));
292}
293
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700294} // namespace libcontainer