blob: 8763cc0e9901c0757f01e41c0d3e7700ba5049b4 [file] [log] [blame]
Luis Hector Chavez58725a82017-09-19 21:14:17 -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.
Dylan Reid837c74a2016-01-22 17:25:21 -08004
Dylan Reid837c74a2016-01-22 17:25:21 -08005#include <errno.h>
6#include <signal.h>
yusukesbbc37a72017-11-21 09:51:54 -08007#include <stdlib.h>
8#include <string.h>
Dylan Reid837c74a2016-01-22 17:25:21 -08009#include <sys/mount.h>
10#include <sys/stat.h>
11#include <sys/types.h>
12#include <unistd.h>
13
Luis Hector Chavez644d2042017-09-19 18:56:44 -070014#include <map>
Luis Hector Chavezedec56e2017-09-19 15:43:53 -070015#include <memory>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070016#include <string>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070017#include <utility>
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070018#include <vector>
Luis Hector Chavezedec56e2017-09-19 15:43:53 -070019
Luis Hector Chavez644d2042017-09-19 18:56:44 -070020#include <base/bind.h>
21#include <base/bind_helpers.h>
Luis Hector Chavez5381d002017-09-16 12:54:24 -070022#include <base/files/file_path.h>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070023#include <base/files/file_util.h>
24#include <base/files/scoped_temp_dir.h>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070025#include <base/posix/eintr_wrapper.h>
yusukesbbc37a72017-11-21 09:51:54 -080026#include <base/strings/string_split.h>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070027#include <gtest/gtest.h>
Dylan Reid837c74a2016-01-22 17:25:21 -080028
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070029#include "libcontainer/cgroup.h"
30#include "libcontainer/config.h"
31#include "libcontainer/container.h"
Luis Hector Chavez836d7b22017-09-14 15:11:15 -070032#include "libcontainer/libcontainer.h"
Luis Hector Chavez835d39e2017-09-19 15:16:31 -070033#include "libcontainer/libcontainer_util.h"
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070034
Luis Hector Chavez58725a82017-09-19 21:14:17 -070035namespace libcontainer {
36
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070037namespace {
38
Luis Hector Chavez644d2042017-09-19 18:56:44 -070039using MinijailHookCallback = base::Callback<int()>;
40
Luis Hector Chavez58725a82017-09-19 21:14:17 -070041constexpr int kTestCpuShares = 200;
42constexpr int kTestCpuQuota = 20000;
43constexpr int kTestCpuPeriod = 50000;
44
45struct MockPosixState {
46 struct MountArgs {
47 std::string source;
48 base::FilePath target;
49 std::string filesystemtype;
50 unsigned long mountflags;
51 const void* data;
52 bool outside_mount;
53 };
54 std::vector<MountArgs> mount_args;
55
56 dev_t stat_rdev_ret = makedev(2, 3);
57
58 std::vector<int> kill_sigs;
59 base::FilePath mkdtemp_root;
60};
61MockPosixState* g_mock_posix_state = nullptr;
62
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070063struct MockCgroupState {
64 struct AddedDevice {
65 bool allow;
66 int major;
67 int minor;
68 bool read;
69 bool write;
70 bool modify;
71 char type;
72 };
73
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070074 bool freeze_ret = true;
75 bool thaw_ret = true;
76 bool deny_all_devs_ret = true;
77 bool add_device_ret = true;
78 bool set_cpu_ret = true;
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070079
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070080 int deny_all_devs_called_count;
81
82 std::vector<AddedDevice> added_devices;
83
84 int set_cpu_shares_count;
85 int set_cpu_quota_count;
86 int set_cpu_period_count;
87 int set_cpu_rt_runtime_count;
88 int set_cpu_rt_period_count;
89};
90MockCgroupState* g_mock_cgroup_state = nullptr;
91
92class MockCgroup : public libcontainer::Cgroup {
93 public:
94 explicit MockCgroup(MockCgroupState* state) : state_(state) {}
95 ~MockCgroup() = default;
96
97 static std::unique_ptr<libcontainer::Cgroup> Create(
98 base::StringPiece name,
99 const base::FilePath& cgroup_root,
100 const base::FilePath& cgroup_parent,
101 uid_t cgroup_owner,
102 gid_t cgroup_group) {
Ben Chanc4929c62017-09-29 23:25:39 -0700103 return std::make_unique<MockCgroup>(g_mock_cgroup_state);
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700104 }
105
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700106 bool Freeze() override { return state_->freeze_ret; }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700107
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700108 bool Thaw() override { return state_->thaw_ret; }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700109
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700110 bool DenyAllDevices() override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700111 ++state_->deny_all_devs_called_count;
112 return state_->deny_all_devs_ret;
113 }
114
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700115 bool AddDevice(bool allow,
116 int major,
117 int minor,
118 bool read,
119 bool write,
120 bool modify,
121 char type) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700122 state_->added_devices.emplace_back(MockCgroupState::AddedDevice{
123 allow, major, minor, read, write, modify, type});
124 return state_->add_device_ret;
125 }
126
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700127 bool SetCpuShares(int shares) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700128 state_->set_cpu_shares_count++;
129 return state_->set_cpu_ret;
130 }
131
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700132 bool SetCpuQuota(int quota) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700133 state_->set_cpu_quota_count++;
134 return state_->set_cpu_ret;
135 }
136
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700137 bool SetCpuPeriod(int period) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700138 state_->set_cpu_period_count++;
139 return state_->set_cpu_ret;
140 }
141
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700142 bool SetCpuRtRuntime(int rt_runtime) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700143 state_->set_cpu_rt_runtime_count++;
144 return state_->set_cpu_ret;
145 }
146
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700147 bool SetCpuRtPeriod(int rt_period) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700148 state_->set_cpu_rt_period_count++;
149 return state_->set_cpu_ret;
150 }
151
152 private:
153 MockCgroupState* const state_;
154
155 DISALLOW_COPY_AND_ASSIGN(MockCgroup);
156};
157
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700158struct MockMinijailState {
159 std::string alt_syscall_table;
160 int ipc_called_count;
161 int vfs_called_count;
162 int net_called_count;
163 int pids_called_count;
164 int run_as_init_called_count;
165 int user_called_count;
166 int cgroups_called_count;
167 int wait_called_count;
168 int reset_signal_mask_called_count;
Luis Hector Chavezcd9a6b62018-04-04 08:39:44 -0700169 int reset_signal_handlers_called_count;
Risanfd41aee2018-08-15 14:03:38 +0900170 int set_supplementary_gids_called_count;
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700171 int pid;
172 std::map<minijail_hook_event_t, std::vector<MinijailHookCallback>> hooks;
173};
174MockMinijailState* g_mock_minijail_state = nullptr;
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700175
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700176} // namespace
Dylan Reid837c74a2016-01-22 17:25:21 -0800177
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700178TEST(LibcontainerTest, PremountedRunfs) {
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700179 char premounted_runfs[] = "/tmp/cgtest_run/root";
180 struct container_config* config = container_config_create();
181 ASSERT_NE(nullptr, config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700182
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700183 container_config_premounted_runfs(config, premounted_runfs);
184 const char* result = container_config_get_premounted_runfs(config);
185 ASSERT_EQ(0, strcmp(result, premounted_runfs));
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700186
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700187 container_config_destroy(config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700188}
189
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700190TEST(LibcontainerTest, PidFilePath) {
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700191 char pid_file_path[] = "/tmp/cgtest_run/root/container.pid";
192 struct container_config* config = container_config_create();
193 ASSERT_NE(nullptr, config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700194
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700195 container_config_pid_file(config, pid_file_path);
196 const char* result = container_config_get_pid_file(config);
197 ASSERT_EQ(0, strcmp(result, pid_file_path));
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700198
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700199 container_config_destroy(config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700200}
201
yusukesbbc37a72017-11-21 09:51:54 -0800202TEST(LibcontainerTest, DumpConfig) {
203 struct container_config* config = container_config_create();
204 ASSERT_NE(nullptr, config);
205
206 // Confirm that container_config_dump() returns a non-empty string.
207 std::unique_ptr<char, decltype(&free)> config_str(
yusukes32622542018-01-05 18:59:52 -0800208 container_config_dump(config, false /* sort_vector */), free);
yusukesbbc37a72017-11-21 09:51:54 -0800209 ASSERT_NE(nullptr, config_str.get());
210 EXPECT_NE(0U, strlen(config_str.get()));
211
212 // Also confirm that the string has multiple lines.
213 EXPECT_LT(1U, base::SplitString(config_str.get(), "\n", base::KEEP_WHITESPACE,
214 base::SPLIT_WANT_NONEMPTY)
215 .size());
216
217 container_config_destroy(config);
218}
219
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700220class ContainerTest : public ::testing::Test {
221 public:
222 ContainerTest() = default;
223 ~ContainerTest() override = default;
Dylan Reid837c74a2016-01-22 17:25:21 -0800224
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700225 void SetUp() override {
226 g_mock_posix_state = new MockPosixState();
227 g_mock_cgroup_state = new MockCgroupState();
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700228 g_mock_minijail_state = new MockMinijailState();
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700229 libcontainer::Cgroup::SetCgroupFactoryForTesting(&MockCgroup::Create);
Dylan Reid837c74a2016-01-22 17:25:21 -0800230
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700231 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700232
Satoru Takabayashicf730fb2018-08-03 16:42:36 +0900233 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_.GetPath(),
234 "container_test", &rootfs_));
Dylan Reid837c74a2016-01-22 17:25:21 -0800235
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700236 mount_flags_ = MS_NOSUID | MS_NODEV | MS_NOEXEC;
Dylan Reid837c74a2016-01-22 17:25:21 -0800237
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700238 config_.reset(new Config());
239 container_config_uid_map(config_->get(), "0 0 4294967295");
240 container_config_gid_map(config_->get(), "0 0 4294967295");
241 container_config_rootfs(config_->get(), rootfs_.value().c_str());
Dylan Reid837c74a2016-01-22 17:25:21 -0800242
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700243 static const char* kArgv[] = {
244 "/sbin/init",
245 };
246 container_config_program_argv(config_->get(), kArgv, 1);
247 container_config_alt_syscall_table(config_->get(), "testsyscalltable");
248 container_config_add_mount(config_->get(),
249 "testtmpfs",
250 "tmpfs",
251 "/tmp",
252 "tmpfs",
253 nullptr,
254 nullptr,
255 mount_flags_,
256 0,
257 1000,
258 1000,
259 0x666,
260 0,
261 0);
262 container_config_add_device(config_->get(),
263 'c',
264 "/dev/foo",
265 S_IRWXU | S_IRWXG,
266 245,
267 2,
268 0,
Stephen Barber7bae6642017-11-30 10:47:12 -0800269 0,
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700270 1000,
271 1001,
272 1,
273 1,
274 0);
275 // test dynamic minor on /dev/null
276 container_config_add_device(config_->get(),
277 'c',
278 "/dev/null",
279 S_IRWXU | S_IRWXG,
280 1,
281 -1,
Stephen Barber7bae6642017-11-30 10:47:12 -0800282 0,
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700283 1,
284 1000,
285 1001,
286 1,
287 1,
288 0);
Stephen Barber771653f2017-10-04 23:48:57 -0700289 static const char* kNamespaces[] = {
290 "cgroup",
291 "ipc",
292 "mount",
293 "network",
294 "pid",
295 "user",
296 };
297 container_config_namespaces(config_->get(), kNamespaces,
298 arraysize(kNamespaces));
Dylan Reid837c74a2016-01-22 17:25:21 -0800299
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700300 container_config_set_cpu_shares(config_->get(), kTestCpuShares);
301 container_config_set_cpu_cfs_params(
302 config_->get(), kTestCpuQuota, kTestCpuPeriod);
303 /* Invalid params, so this won't be applied. */
304 container_config_set_cpu_rt_params(config_->get(), 20000, 20000);
Dylan Reid837c74a2016-01-22 17:25:21 -0800305
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700306 base::FilePath rundir;
Satoru Takabayashicf730fb2018-08-03 16:42:36 +0900307 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_.GetPath(),
308 "container_test_run", &rundir));
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700309 container_.reset(new Container("containerUT", rundir));
310 ASSERT_NE(nullptr, container_.get());
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700311 }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700312
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700313 void TearDown() override {
314 container_.reset();
315 config_.reset();
Dylan Reid837c74a2016-01-22 17:25:21 -0800316
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700317 ASSERT_TRUE(temp_dir_.Delete());
318 delete g_mock_posix_state;
319 g_mock_posix_state = nullptr;
320 libcontainer::Cgroup::SetCgroupFactoryForTesting(nullptr);
321 delete g_mock_cgroup_state;
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700322 delete g_mock_minijail_state;
323 g_mock_minijail_state = nullptr;
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700324 }
325
326 protected:
yusukesbbc37a72017-11-21 09:51:54 -0800327 const Config* config() const { return config_.get(); }
328
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700329 std::unique_ptr<Config> config_;
330 std::unique_ptr<Container> container_;
331 int mount_flags_;
332 base::FilePath rootfs_;
333
334 private:
335 base::ScopedTempDir temp_dir_;
336
337 DISALLOW_COPY_AND_ASSIGN(ContainerTest);
338};
339
340TEST_F(ContainerTest, TestMountTmpStart) {
341 ASSERT_EQ(0, container_start(container_->get(), config_->get()));
342 ASSERT_EQ(2, g_mock_posix_state->mount_args.size());
343 EXPECT_EQ(false, g_mock_posix_state->mount_args[1].outside_mount);
344 EXPECT_STREQ("tmpfs", g_mock_posix_state->mount_args[1].source.c_str());
345 EXPECT_STREQ("/tmp",
346 g_mock_posix_state->mount_args[1].target.value().c_str());
347 EXPECT_STREQ("tmpfs",
348 g_mock_posix_state->mount_args[1].filesystemtype.c_str());
349 EXPECT_EQ(g_mock_posix_state->mount_args[1].mountflags,
350 static_cast<unsigned long>(mount_flags_));
351 EXPECT_EQ(nullptr, g_mock_posix_state->mount_args[1].data);
Dylan Reid837c74a2016-01-22 17:25:21 -0800352
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700353 EXPECT_EQ(1, g_mock_minijail_state->ipc_called_count);
354 EXPECT_EQ(1, g_mock_minijail_state->vfs_called_count);
355 EXPECT_EQ(1, g_mock_minijail_state->net_called_count);
356 EXPECT_EQ(1, g_mock_minijail_state->pids_called_count);
357 EXPECT_EQ(1, g_mock_minijail_state->user_called_count);
358 EXPECT_EQ(1, g_mock_minijail_state->cgroups_called_count);
359 EXPECT_EQ(1, g_mock_minijail_state->run_as_init_called_count);
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700360 EXPECT_EQ(1, g_mock_cgroup_state->deny_all_devs_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800361
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700362 ASSERT_EQ(2, g_mock_cgroup_state->added_devices.size());
363 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].allow);
364 EXPECT_EQ(245, g_mock_cgroup_state->added_devices[0].major);
365 EXPECT_EQ(2, g_mock_cgroup_state->added_devices[0].minor);
366 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].read);
367 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].write);
368 EXPECT_EQ(0, g_mock_cgroup_state->added_devices[0].modify);
369 EXPECT_EQ('c', g_mock_cgroup_state->added_devices[0].type);
Dylan Reid355d5e42016-04-29 16:53:31 -0700370
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700371 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].allow);
372 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].major);
373 EXPECT_EQ(-1, g_mock_cgroup_state->added_devices[1].minor);
374 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].read);
375 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].write);
376 EXPECT_EQ(0, g_mock_cgroup_state->added_devices[1].modify);
377 EXPECT_EQ('c', g_mock_cgroup_state->added_devices[1].type);
Dylan Reid837c74a2016-01-22 17:25:21 -0800378
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700379 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_shares_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700380 EXPECT_EQ(kTestCpuShares, container_config_get_cpu_shares(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700381 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_quota_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700382 EXPECT_EQ(kTestCpuQuota, container_config_get_cpu_quota(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700383 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_period_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700384 EXPECT_EQ(kTestCpuPeriod, container_config_get_cpu_period(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700385 EXPECT_EQ(0, g_mock_cgroup_state->set_cpu_rt_runtime_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700386 EXPECT_EQ(0, container_config_get_cpu_rt_runtime(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700387 EXPECT_EQ(0, g_mock_cgroup_state->set_cpu_rt_period_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700388 EXPECT_EQ(0, container_config_get_cpu_rt_period(config_->get()));
Chinyue Chenfac909e2016-06-24 14:17:42 +0800389
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700390 ASSERT_NE(std::string(), g_mock_minijail_state->alt_syscall_table);
391 EXPECT_EQ("testsyscalltable", g_mock_minijail_state->alt_syscall_table);
Dylan Reid837c74a2016-01-22 17:25:21 -0800392
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700393 EXPECT_EQ(0, container_wait(container_->get()));
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700394 EXPECT_EQ(1, g_mock_minijail_state->wait_called_count);
395 EXPECT_EQ(1, g_mock_minijail_state->reset_signal_mask_called_count);
Luis Hector Chavezcd9a6b62018-04-04 08:39:44 -0700396 EXPECT_EQ(1, g_mock_minijail_state->reset_signal_handlers_called_count);
Risanfd41aee2018-08-15 14:03:38 +0900397 EXPECT_EQ(0, g_mock_minijail_state->set_supplementary_gids_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800398}
399
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700400TEST_F(ContainerTest, TestKillContainer) {
401 ASSERT_EQ(0, container_start(container_->get(), config_->get()));
402 EXPECT_EQ(0, container_kill(container_->get()));
403 EXPECT_EQ(std::vector<int>{SIGKILL}, g_mock_posix_state->kill_sigs);
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700404 EXPECT_EQ(1, g_mock_minijail_state->wait_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800405}
406
yusukesbbc37a72017-11-21 09:51:54 -0800407// Does the same as LibcontainerTest.DumpConfig but with more configuration
408// parameters similar to the production.
409TEST_F(ContainerTest, DumpConfig) {
410 struct container_config* config = this->config()->get();
411 ASSERT_NE(nullptr, config);
412 std::unique_ptr<char, decltype(&free)> config_str(
yusukes32622542018-01-05 18:59:52 -0800413 container_config_dump(config, true /* sort_vector */), free);
yusukesbbc37a72017-11-21 09:51:54 -0800414 ASSERT_NE(nullptr, config_str.get());
415 EXPECT_NE(0U, strlen(config_str.get()));
416 EXPECT_LT(1U, base::SplitString(config_str.get(), "\n", base::KEEP_WHITESPACE,
417 base::SPLIT_WANT_NONEMPTY)
418 .size());
419}
420
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700421} // namespace libcontainer
422
423// libc stubs so the UT doesn't need root to call mount, etc.
Luis Hector Chavezf9b16872017-09-14 14:22:15 -0700424extern "C" {
425
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700426extern decltype(chmod) __real_chmod;
427int __wrap_chmod(const char* path, mode_t mode) {
428 if (!libcontainer::g_mock_posix_state)
429 return __real_chmod(path, mode);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700430 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800431}
432
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700433extern decltype(chown) __real_chown;
434int __wrap_chown(const char* path, uid_t owner, gid_t group) {
435 if (!libcontainer::g_mock_posix_state)
436 return __real_chown(path, owner, group);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700437 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800438}
439
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700440extern decltype(getuid) __real_getuid;
441uid_t __wrap_getuid(void) {
442 if (!libcontainer::g_mock_posix_state)
443 return __real_getuid();
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700444 return 0;
445}
446
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700447extern decltype(kill) __real_kill;
448int __wrap_kill(pid_t pid, int sig) {
449 if (!libcontainer::g_mock_posix_state)
450 return __real_kill(pid, sig);
451 libcontainer::g_mock_posix_state->kill_sigs.push_back(sig);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700452 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800453}
454
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700455extern decltype(mkdir) __real_mkdir;
456int __wrap_mkdir(const char* pathname, mode_t mode) {
457 if (!libcontainer::g_mock_posix_state)
458 return __real_mkdir(pathname, mode);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700459 return 0;
Luis Hector Chavez836d7b22017-09-14 15:11:15 -0700460}
Dylan Reid837c74a2016-01-22 17:25:21 -0800461
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700462extern decltype(mkdtemp) __real_mkdtemp;
463char* __wrap_mkdtemp(char* template_string) {
464 if (!libcontainer::g_mock_posix_state)
465 return __real_mkdtemp(template_string);
466 libcontainer::g_mock_posix_state->mkdtemp_root =
467 base::FilePath(template_string);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700468 return template_string;
Dylan Reid837c74a2016-01-22 17:25:21 -0800469}
470
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700471extern decltype(mount) __real_mount;
472int __wrap_mount(const char* source,
473 const char* target,
474 const char* filesystemtype,
475 unsigned long mountflags,
476 const void* data) {
477 if (!libcontainer::g_mock_posix_state)
478 return __real_mount(source, target, filesystemtype, mountflags, data);
479
480 libcontainer::g_mock_posix_state->mount_args.emplace_back(
481 libcontainer::MockPosixState::MountArgs{source,
482 base::FilePath(target),
483 filesystemtype,
484 mountflags,
485 data,
486 true});
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700487 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800488}
489
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700490extern decltype(rmdir) __real_rmdir;
491int __wrap_rmdir(const char* pathname) {
492 if (!libcontainer::g_mock_posix_state)
493 return __real_rmdir(pathname);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700494 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800495}
496
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700497extern decltype(umount) __real_umount;
498int __wrap_umount(const char* target) {
499 if (!libcontainer::g_mock_posix_state)
500 return __real_umount(target);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700501 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800502}
503
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700504extern decltype(umount2) __real_umount2;
505int __wrap_umount2(const char* target, int flags) {
506 if (!libcontainer::g_mock_posix_state)
507 return __real_umount2(target, flags);
508 return 0;
509}
510
511extern decltype(unlink) __real_unlink;
512int __wrap_unlink(const char* pathname) {
513 if (!libcontainer::g_mock_posix_state)
514 return __real_unlink(pathname);
515 return 0;
516}
517
518extern decltype(__xmknod) __real___xmknod;
519int __wrap___xmknod(int ver, const char* pathname, mode_t mode, dev_t* dev) {
520 if (!libcontainer::g_mock_posix_state)
521 return __real___xmknod(ver, pathname, mode, dev);
522 return 0;
523}
524
525extern decltype(__xstat) __real___xstat;
526int __wrap___xstat(int ver, const char* path, struct stat* buf) {
527 if (!libcontainer::g_mock_posix_state)
528 return __real___xstat(ver, path, buf);
529 buf->st_rdev = libcontainer::g_mock_posix_state->stat_rdev_ret;
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700530 return 0;
531}
532
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700533extern decltype(setns) __real_setns;
534int __wrap_setns(int fd, int nstype) {
535 if (!libcontainer::g_mock_posix_state)
536 return __real_setns(fd, nstype);
537 return 0;
538}
539
Dylan Reid837c74a2016-01-22 17:25:21 -0800540/* Minijail stubs */
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700541struct minijail* minijail_new(void) {
542 return (struct minijail*)0x55;
Chinyue Chen03c54ae2016-06-29 12:29:10 +0800543}
544
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700545void minijail_destroy(struct minijail* j) {}
546
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700547int minijail_mount_with_data(struct minijail* j,
548 const char* source,
549 const char* target,
550 const char* filesystemtype,
551 unsigned long mountflags,
552 const char* data) {
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700553 libcontainer::g_mock_posix_state->mount_args.emplace_back(
554 libcontainer::MockPosixState::MountArgs{source,
555 base::FilePath(target),
556 filesystemtype,
557 mountflags,
558 data,
559 false});
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700560 return 0;
561}
562
Luis Hector Chavezedec56e2017-09-19 15:43:53 -0700563void minijail_namespace_user_disable_setgroups(struct minijail* j) {}
Dylan Reid837c74a2016-01-22 17:25:21 -0800564
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700565void minijail_namespace_vfs(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700566 ++libcontainer::g_mock_minijail_state->vfs_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800567}
568
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700569void minijail_namespace_ipc(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700570 ++libcontainer::g_mock_minijail_state->ipc_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800571}
572
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700573void minijail_namespace_net(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700574 ++libcontainer::g_mock_minijail_state->net_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800575}
576
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700577void minijail_namespace_pids(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700578 ++libcontainer::g_mock_minijail_state->pids_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800579}
580
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700581void minijail_namespace_user(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700582 ++libcontainer::g_mock_minijail_state->user_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800583}
584
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700585void minijail_namespace_cgroups(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700586 ++libcontainer::g_mock_minijail_state->cgroups_called_count;
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700587}
588
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700589int minijail_uidmap(struct minijail* j, const char* uidmap) {
590 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800591}
592
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700593int minijail_gidmap(struct minijail* j, const char* gidmap) {
594 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800595}
596
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700597int minijail_enter_pivot_root(struct minijail* j, const char* dir) {
598 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800599}
600
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700601void minijail_run_as_init(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700602 ++libcontainer::g_mock_minijail_state->run_as_init_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800603}
604
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700605int minijail_run_pid_pipes_no_preload(struct minijail* j,
606 const char* filename,
607 char* const argv[],
608 pid_t* pchild_pid,
609 int* pstdin_fd,
610 int* pstdout_fd,
611 int* pstderr_fd) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700612 libcontainer::g_mock_minijail_state->pid = fork();
613 if (libcontainer::g_mock_minijail_state->pid == -1)
614 return libcontainer::g_mock_minijail_state->pid;
615
616 if (libcontainer::g_mock_minijail_state->pid == 0) {
617 for (minijail_hook_event_t event : {MINIJAIL_HOOK_EVENT_PRE_CHROOT,
618 MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS,
619 MINIJAIL_HOOK_EVENT_PRE_EXECVE}) {
620 auto it = libcontainer::g_mock_minijail_state->hooks.find(event);
621 if (it == libcontainer::g_mock_minijail_state->hooks.end())
622 continue;
623 for (auto& hook : it->second) {
624 int rc = hook.Run();
625 if (rc)
626 _exit(rc);
627 }
628 }
629 _exit(0);
630 }
631
632 *pchild_pid = libcontainer::g_mock_minijail_state->pid;
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700633 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800634}
635
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700636int minijail_write_pid_file(struct minijail* j, const char* path) {
637 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800638}
639
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700640int minijail_wait(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700641 ++libcontainer::g_mock_minijail_state->wait_called_count;
642 int status;
643 if (HANDLE_EINTR(
644 waitpid(libcontainer::g_mock_minijail_state->pid, &status, 0)) < 0) {
Luis Hector Chavezdc61f8d2017-10-02 11:12:46 -0700645 PLOG(ERROR) << "Failed to wait for minijail";
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700646 return -errno;
647 }
648 if (!WIFEXITED(status)) {
649 LOG(ERROR) << "minijail terminated abnormally: " << std::hex << status;
650 return -ECANCELED;
651 }
652 // Exit status gets truncated to 8 bits. This should sign-extend it so that
653 // any negative values we passed are preserved.
654 return static_cast<int8_t>(WEXITSTATUS(status));
Dylan Reid837c74a2016-01-22 17:25:21 -0800655}
656
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700657int minijail_use_alt_syscall(struct minijail* j, const char* table) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700658 libcontainer::g_mock_minijail_state->alt_syscall_table = table;
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700659 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800660}
661
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700662int minijail_add_to_cgroup(struct minijail* j, const char* cg_path) {
663 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800664}
665
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700666void minijail_reset_signal_mask(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700667 ++libcontainer::g_mock_minijail_state->reset_signal_mask_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800668}
669
Luis Hector Chavezcd9a6b62018-04-04 08:39:44 -0700670void minijail_reset_signal_handlers(struct minijail* j) {
671 ++libcontainer::g_mock_minijail_state->reset_signal_handlers_called_count;
672}
673
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700674void minijail_skip_remount_private(struct minijail* j) {}
Dylan Reid837c74a2016-01-22 17:25:21 -0800675
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700676int minijail_preserve_fd(struct minijail* j, int parent_fd, int child_fd) {
677 return 0;
678}
679
680int minijail_add_hook(struct minijail* j,
681 minijail_hook_t hook,
682 void* payload,
683 minijail_hook_event_t event) {
684 auto it = libcontainer::g_mock_minijail_state->hooks.insert(
685 std::make_pair(event, std::vector<libcontainer::MinijailHookCallback>()));
686 it.first->second.emplace_back(base::Bind(hook, base::Unretained(payload)));
687 return 0;
688}
689
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700690void minijail_close_open_fds(struct minijail* j) {}
691
Risanfd41aee2018-08-15 14:03:38 +0900692void minijail_set_supplementary_gids(struct minijail* j,
693 size_t size,
694 const gid_t* list) {
695 ++libcontainer::g_mock_minijail_state->set_supplementary_gids_called_count;
696}
697
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700698} // extern "C"