blob: d9b1e307329e84cb8e4059ab170adc2314a92662 [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>
7#include <sys/mount.h>
8#include <sys/stat.h>
9#include <sys/types.h>
10#include <unistd.h>
11
Luis Hector Chavez644d2042017-09-19 18:56:44 -070012#include <map>
Luis Hector Chavezedec56e2017-09-19 15:43:53 -070013#include <memory>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070014#include <string>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070015#include <utility>
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070016#include <vector>
Luis Hector Chavezedec56e2017-09-19 15:43:53 -070017
Luis Hector Chavez644d2042017-09-19 18:56:44 -070018#include <base/bind.h>
19#include <base/bind_helpers.h>
Luis Hector Chavez5381d002017-09-16 12:54:24 -070020#include <base/files/file_path.h>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070021#include <base/files/file_util.h>
22#include <base/files/scoped_temp_dir.h>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070023#include <base/posix/eintr_wrapper.h>
Luis Hector Chavez58725a82017-09-19 21:14:17 -070024#include <gtest/gtest.h>
Dylan Reid837c74a2016-01-22 17:25:21 -080025
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070026#include "libcontainer/cgroup.h"
27#include "libcontainer/config.h"
28#include "libcontainer/container.h"
Luis Hector Chavez836d7b22017-09-14 15:11:15 -070029#include "libcontainer/libcontainer.h"
Luis Hector Chavez835d39e2017-09-19 15:16:31 -070030#include "libcontainer/libcontainer_util.h"
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070031
Luis Hector Chavez58725a82017-09-19 21:14:17 -070032namespace libcontainer {
33
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070034namespace {
35
Luis Hector Chavez644d2042017-09-19 18:56:44 -070036using MinijailHookCallback = base::Callback<int()>;
37
Luis Hector Chavez58725a82017-09-19 21:14:17 -070038constexpr int kTestCpuShares = 200;
39constexpr int kTestCpuQuota = 20000;
40constexpr int kTestCpuPeriod = 50000;
41
42struct MockPosixState {
43 struct MountArgs {
44 std::string source;
45 base::FilePath target;
46 std::string filesystemtype;
47 unsigned long mountflags;
48 const void* data;
49 bool outside_mount;
50 };
51 std::vector<MountArgs> mount_args;
52
53 dev_t stat_rdev_ret = makedev(2, 3);
54
55 std::vector<int> kill_sigs;
56 base::FilePath mkdtemp_root;
57};
58MockPosixState* g_mock_posix_state = nullptr;
59
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070060struct MockCgroupState {
61 struct AddedDevice {
62 bool allow;
63 int major;
64 int minor;
65 bool read;
66 bool write;
67 bool modify;
68 char type;
69 };
70
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070071 bool freeze_ret = true;
72 bool thaw_ret = true;
73 bool deny_all_devs_ret = true;
74 bool add_device_ret = true;
75 bool set_cpu_ret = true;
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070076
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -070077 int deny_all_devs_called_count;
78
79 std::vector<AddedDevice> added_devices;
80
81 int set_cpu_shares_count;
82 int set_cpu_quota_count;
83 int set_cpu_period_count;
84 int set_cpu_rt_runtime_count;
85 int set_cpu_rt_period_count;
86};
87MockCgroupState* g_mock_cgroup_state = nullptr;
88
89class MockCgroup : public libcontainer::Cgroup {
90 public:
91 explicit MockCgroup(MockCgroupState* state) : state_(state) {}
92 ~MockCgroup() = default;
93
94 static std::unique_ptr<libcontainer::Cgroup> Create(
95 base::StringPiece name,
96 const base::FilePath& cgroup_root,
97 const base::FilePath& cgroup_parent,
98 uid_t cgroup_owner,
99 gid_t cgroup_group) {
Ben Chanc4929c62017-09-29 23:25:39 -0700100 return std::make_unique<MockCgroup>(g_mock_cgroup_state);
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700101 }
102
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700103 bool Freeze() override { return state_->freeze_ret; }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700104
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700105 bool Thaw() override { return state_->thaw_ret; }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700106
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700107 bool DenyAllDevices() override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700108 ++state_->deny_all_devs_called_count;
109 return state_->deny_all_devs_ret;
110 }
111
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700112 bool AddDevice(bool allow,
113 int major,
114 int minor,
115 bool read,
116 bool write,
117 bool modify,
118 char type) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700119 state_->added_devices.emplace_back(MockCgroupState::AddedDevice{
120 allow, major, minor, read, write, modify, type});
121 return state_->add_device_ret;
122 }
123
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700124 bool SetCpuShares(int shares) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700125 state_->set_cpu_shares_count++;
126 return state_->set_cpu_ret;
127 }
128
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700129 bool SetCpuQuota(int quota) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700130 state_->set_cpu_quota_count++;
131 return state_->set_cpu_ret;
132 }
133
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700134 bool SetCpuPeriod(int period) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700135 state_->set_cpu_period_count++;
136 return state_->set_cpu_ret;
137 }
138
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700139 bool SetCpuRtRuntime(int rt_runtime) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700140 state_->set_cpu_rt_runtime_count++;
141 return state_->set_cpu_ret;
142 }
143
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700144 bool SetCpuRtPeriod(int rt_period) override {
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700145 state_->set_cpu_rt_period_count++;
146 return state_->set_cpu_ret;
147 }
148
149 private:
150 MockCgroupState* const state_;
151
152 DISALLOW_COPY_AND_ASSIGN(MockCgroup);
153};
154
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700155struct MockMinijailState {
156 std::string alt_syscall_table;
157 int ipc_called_count;
158 int vfs_called_count;
159 int net_called_count;
160 int pids_called_count;
161 int run_as_init_called_count;
162 int user_called_count;
163 int cgroups_called_count;
164 int wait_called_count;
165 int reset_signal_mask_called_count;
166 int pid;
167 std::map<minijail_hook_event_t, std::vector<MinijailHookCallback>> hooks;
168};
169MockMinijailState* g_mock_minijail_state = nullptr;
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700170
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700171} // namespace
Dylan Reid837c74a2016-01-22 17:25:21 -0800172
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700173TEST(LibcontainerTest, PremountedRunfs) {
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700174 char premounted_runfs[] = "/tmp/cgtest_run/root";
175 struct container_config* config = container_config_create();
176 ASSERT_NE(nullptr, config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700177
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700178 container_config_premounted_runfs(config, premounted_runfs);
179 const char* result = container_config_get_premounted_runfs(config);
180 ASSERT_EQ(0, strcmp(result, premounted_runfs));
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700181
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700182 container_config_destroy(config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700183}
184
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700185TEST(LibcontainerTest, PidFilePath) {
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700186 char pid_file_path[] = "/tmp/cgtest_run/root/container.pid";
187 struct container_config* config = container_config_create();
188 ASSERT_NE(nullptr, config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700189
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700190 container_config_pid_file(config, pid_file_path);
191 const char* result = container_config_get_pid_file(config);
192 ASSERT_EQ(0, strcmp(result, pid_file_path));
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700193
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700194 container_config_destroy(config);
Keshav Santhanam0e4c3282016-07-14 10:25:16 -0700195}
196
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700197class ContainerTest : public ::testing::Test {
198 public:
199 ContainerTest() = default;
200 ~ContainerTest() override = default;
Dylan Reid837c74a2016-01-22 17:25:21 -0800201
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700202 void SetUp() override {
203 g_mock_posix_state = new MockPosixState();
204 g_mock_cgroup_state = new MockCgroupState();
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700205 g_mock_minijail_state = new MockMinijailState();
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700206 libcontainer::Cgroup::SetCgroupFactoryForTesting(&MockCgroup::Create);
Dylan Reid837c74a2016-01-22 17:25:21 -0800207
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700208 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700209
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700210 ASSERT_TRUE(base::CreateTemporaryDirInDir(
211 temp_dir_.path(), FILE_PATH_LITERAL("container_test"), &rootfs_));
Dylan Reid837c74a2016-01-22 17:25:21 -0800212
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700213 mount_flags_ = MS_NOSUID | MS_NODEV | MS_NOEXEC;
Dylan Reid837c74a2016-01-22 17:25:21 -0800214
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700215 config_.reset(new Config());
216 container_config_uid_map(config_->get(), "0 0 4294967295");
217 container_config_gid_map(config_->get(), "0 0 4294967295");
218 container_config_rootfs(config_->get(), rootfs_.value().c_str());
Dylan Reid837c74a2016-01-22 17:25:21 -0800219
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700220 static const char* kArgv[] = {
221 "/sbin/init",
222 };
223 container_config_program_argv(config_->get(), kArgv, 1);
224 container_config_alt_syscall_table(config_->get(), "testsyscalltable");
225 container_config_add_mount(config_->get(),
226 "testtmpfs",
227 "tmpfs",
228 "/tmp",
229 "tmpfs",
230 nullptr,
231 nullptr,
232 mount_flags_,
233 0,
234 1000,
235 1000,
236 0x666,
237 0,
238 0);
239 container_config_add_device(config_->get(),
240 'c',
241 "/dev/foo",
242 S_IRWXU | S_IRWXG,
243 245,
244 2,
245 0,
246 1000,
247 1001,
248 1,
249 1,
250 0);
251 // test dynamic minor on /dev/null
252 container_config_add_device(config_->get(),
253 'c',
254 "/dev/null",
255 S_IRWXU | S_IRWXG,
256 1,
257 -1,
258 1,
259 1000,
260 1001,
261 1,
262 1,
263 0);
Stephen Barber771653f2017-10-04 23:48:57 -0700264 static const char* kNamespaces[] = {
265 "cgroup",
266 "ipc",
267 "mount",
268 "network",
269 "pid",
270 "user",
271 };
272 container_config_namespaces(config_->get(), kNamespaces,
273 arraysize(kNamespaces));
Dylan Reid837c74a2016-01-22 17:25:21 -0800274
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700275 container_config_set_cpu_shares(config_->get(), kTestCpuShares);
276 container_config_set_cpu_cfs_params(
277 config_->get(), kTestCpuQuota, kTestCpuPeriod);
278 /* Invalid params, so this won't be applied. */
279 container_config_set_cpu_rt_params(config_->get(), 20000, 20000);
Dylan Reid837c74a2016-01-22 17:25:21 -0800280
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700281 base::FilePath rundir;
282 ASSERT_TRUE(base::CreateTemporaryDirInDir(
283 temp_dir_.path(), FILE_PATH_LITERAL("container_test_run"), &rundir));
284 container_.reset(new Container("containerUT", rundir));
285 ASSERT_NE(nullptr, container_.get());
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700286 }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700287
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700288 void TearDown() override {
289 container_.reset();
290 config_.reset();
Dylan Reid837c74a2016-01-22 17:25:21 -0800291
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700292 ASSERT_TRUE(temp_dir_.Delete());
293 delete g_mock_posix_state;
294 g_mock_posix_state = nullptr;
295 libcontainer::Cgroup::SetCgroupFactoryForTesting(nullptr);
296 delete g_mock_cgroup_state;
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700297 delete g_mock_minijail_state;
298 g_mock_minijail_state = nullptr;
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700299 }
300
301 protected:
302 std::unique_ptr<Config> config_;
303 std::unique_ptr<Container> container_;
304 int mount_flags_;
305 base::FilePath rootfs_;
306
307 private:
308 base::ScopedTempDir temp_dir_;
309
310 DISALLOW_COPY_AND_ASSIGN(ContainerTest);
311};
312
313TEST_F(ContainerTest, TestMountTmpStart) {
314 ASSERT_EQ(0, container_start(container_->get(), config_->get()));
315 ASSERT_EQ(2, g_mock_posix_state->mount_args.size());
316 EXPECT_EQ(false, g_mock_posix_state->mount_args[1].outside_mount);
317 EXPECT_STREQ("tmpfs", g_mock_posix_state->mount_args[1].source.c_str());
318 EXPECT_STREQ("/tmp",
319 g_mock_posix_state->mount_args[1].target.value().c_str());
320 EXPECT_STREQ("tmpfs",
321 g_mock_posix_state->mount_args[1].filesystemtype.c_str());
322 EXPECT_EQ(g_mock_posix_state->mount_args[1].mountflags,
323 static_cast<unsigned long>(mount_flags_));
324 EXPECT_EQ(nullptr, g_mock_posix_state->mount_args[1].data);
Dylan Reid837c74a2016-01-22 17:25:21 -0800325
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700326 EXPECT_EQ(1, g_mock_minijail_state->ipc_called_count);
327 EXPECT_EQ(1, g_mock_minijail_state->vfs_called_count);
328 EXPECT_EQ(1, g_mock_minijail_state->net_called_count);
329 EXPECT_EQ(1, g_mock_minijail_state->pids_called_count);
330 EXPECT_EQ(1, g_mock_minijail_state->user_called_count);
331 EXPECT_EQ(1, g_mock_minijail_state->cgroups_called_count);
332 EXPECT_EQ(1, g_mock_minijail_state->run_as_init_called_count);
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700333 EXPECT_EQ(1, g_mock_cgroup_state->deny_all_devs_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800334
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700335 ASSERT_EQ(2, g_mock_cgroup_state->added_devices.size());
336 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].allow);
337 EXPECT_EQ(245, g_mock_cgroup_state->added_devices[0].major);
338 EXPECT_EQ(2, g_mock_cgroup_state->added_devices[0].minor);
339 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].read);
340 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].write);
341 EXPECT_EQ(0, g_mock_cgroup_state->added_devices[0].modify);
342 EXPECT_EQ('c', g_mock_cgroup_state->added_devices[0].type);
Dylan Reid355d5e42016-04-29 16:53:31 -0700343
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700344 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].allow);
345 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].major);
346 EXPECT_EQ(-1, g_mock_cgroup_state->added_devices[1].minor);
347 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].read);
348 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].write);
349 EXPECT_EQ(0, g_mock_cgroup_state->added_devices[1].modify);
350 EXPECT_EQ('c', g_mock_cgroup_state->added_devices[1].type);
Dylan Reid837c74a2016-01-22 17:25:21 -0800351
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700352 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_shares_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700353 EXPECT_EQ(kTestCpuShares, container_config_get_cpu_shares(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700354 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_quota_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700355 EXPECT_EQ(kTestCpuQuota, container_config_get_cpu_quota(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700356 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_period_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700357 EXPECT_EQ(kTestCpuPeriod, container_config_get_cpu_period(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700358 EXPECT_EQ(0, g_mock_cgroup_state->set_cpu_rt_runtime_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700359 EXPECT_EQ(0, container_config_get_cpu_rt_runtime(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700360 EXPECT_EQ(0, g_mock_cgroup_state->set_cpu_rt_period_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700361 EXPECT_EQ(0, container_config_get_cpu_rt_period(config_->get()));
Chinyue Chenfac909e2016-06-24 14:17:42 +0800362
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700363 ASSERT_NE(std::string(), g_mock_minijail_state->alt_syscall_table);
364 EXPECT_EQ("testsyscalltable", g_mock_minijail_state->alt_syscall_table);
Dylan Reid837c74a2016-01-22 17:25:21 -0800365
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700366 EXPECT_EQ(0, container_wait(container_->get()));
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700367 EXPECT_EQ(1, g_mock_minijail_state->wait_called_count);
368 EXPECT_EQ(1, g_mock_minijail_state->reset_signal_mask_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800369}
370
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700371TEST_F(ContainerTest, TestKillContainer) {
372 ASSERT_EQ(0, container_start(container_->get(), config_->get()));
373 EXPECT_EQ(0, container_kill(container_->get()));
374 EXPECT_EQ(std::vector<int>{SIGKILL}, g_mock_posix_state->kill_sigs);
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700375 EXPECT_EQ(1, g_mock_minijail_state->wait_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800376}
377
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700378} // namespace libcontainer
379
380// libc stubs so the UT doesn't need root to call mount, etc.
Luis Hector Chavezf9b16872017-09-14 14:22:15 -0700381extern "C" {
382
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700383extern decltype(chmod) __real_chmod;
384int __wrap_chmod(const char* path, mode_t mode) {
385 if (!libcontainer::g_mock_posix_state)
386 return __real_chmod(path, mode);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700387 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800388}
389
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700390extern decltype(chown) __real_chown;
391int __wrap_chown(const char* path, uid_t owner, gid_t group) {
392 if (!libcontainer::g_mock_posix_state)
393 return __real_chown(path, owner, group);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700394 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800395}
396
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700397extern decltype(getuid) __real_getuid;
398uid_t __wrap_getuid(void) {
399 if (!libcontainer::g_mock_posix_state)
400 return __real_getuid();
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700401 return 0;
402}
403
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700404extern decltype(kill) __real_kill;
405int __wrap_kill(pid_t pid, int sig) {
406 if (!libcontainer::g_mock_posix_state)
407 return __real_kill(pid, sig);
408 libcontainer::g_mock_posix_state->kill_sigs.push_back(sig);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700409 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800410}
411
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700412extern decltype(mkdir) __real_mkdir;
413int __wrap_mkdir(const char* pathname, mode_t mode) {
414 if (!libcontainer::g_mock_posix_state)
415 return __real_mkdir(pathname, mode);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700416 return 0;
Luis Hector Chavez836d7b22017-09-14 15:11:15 -0700417}
Dylan Reid837c74a2016-01-22 17:25:21 -0800418
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700419extern decltype(mkdtemp) __real_mkdtemp;
420char* __wrap_mkdtemp(char* template_string) {
421 if (!libcontainer::g_mock_posix_state)
422 return __real_mkdtemp(template_string);
423 libcontainer::g_mock_posix_state->mkdtemp_root =
424 base::FilePath(template_string);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700425 return template_string;
Dylan Reid837c74a2016-01-22 17:25:21 -0800426}
427
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700428extern decltype(mount) __real_mount;
429int __wrap_mount(const char* source,
430 const char* target,
431 const char* filesystemtype,
432 unsigned long mountflags,
433 const void* data) {
434 if (!libcontainer::g_mock_posix_state)
435 return __real_mount(source, target, filesystemtype, mountflags, data);
436
437 libcontainer::g_mock_posix_state->mount_args.emplace_back(
438 libcontainer::MockPosixState::MountArgs{source,
439 base::FilePath(target),
440 filesystemtype,
441 mountflags,
442 data,
443 true});
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700444 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800445}
446
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700447extern decltype(rmdir) __real_rmdir;
448int __wrap_rmdir(const char* pathname) {
449 if (!libcontainer::g_mock_posix_state)
450 return __real_rmdir(pathname);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700451 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800452}
453
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700454extern decltype(umount) __real_umount;
455int __wrap_umount(const char* target) {
456 if (!libcontainer::g_mock_posix_state)
457 return __real_umount(target);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700458 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800459}
460
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700461extern decltype(umount2) __real_umount2;
462int __wrap_umount2(const char* target, int flags) {
463 if (!libcontainer::g_mock_posix_state)
464 return __real_umount2(target, flags);
465 return 0;
466}
467
468extern decltype(unlink) __real_unlink;
469int __wrap_unlink(const char* pathname) {
470 if (!libcontainer::g_mock_posix_state)
471 return __real_unlink(pathname);
472 return 0;
473}
474
475extern decltype(__xmknod) __real___xmknod;
476int __wrap___xmknod(int ver, const char* pathname, mode_t mode, dev_t* dev) {
477 if (!libcontainer::g_mock_posix_state)
478 return __real___xmknod(ver, pathname, mode, dev);
479 return 0;
480}
481
482extern decltype(__xstat) __real___xstat;
483int __wrap___xstat(int ver, const char* path, struct stat* buf) {
484 if (!libcontainer::g_mock_posix_state)
485 return __real___xstat(ver, path, buf);
486 buf->st_rdev = libcontainer::g_mock_posix_state->stat_rdev_ret;
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700487 return 0;
488}
489
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700490extern decltype(setns) __real_setns;
491int __wrap_setns(int fd, int nstype) {
492 if (!libcontainer::g_mock_posix_state)
493 return __real_setns(fd, nstype);
494 return 0;
495}
496
Dylan Reid837c74a2016-01-22 17:25:21 -0800497/* Minijail stubs */
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700498struct minijail* minijail_new(void) {
499 return (struct minijail*)0x55;
Chinyue Chen03c54ae2016-06-29 12:29:10 +0800500}
501
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700502void minijail_destroy(struct minijail* j) {}
503
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700504int minijail_mount_with_data(struct minijail* j,
505 const char* source,
506 const char* target,
507 const char* filesystemtype,
508 unsigned long mountflags,
509 const char* data) {
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700510 libcontainer::g_mock_posix_state->mount_args.emplace_back(
511 libcontainer::MockPosixState::MountArgs{source,
512 base::FilePath(target),
513 filesystemtype,
514 mountflags,
515 data,
516 false});
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700517 return 0;
518}
519
Luis Hector Chavezedec56e2017-09-19 15:43:53 -0700520void minijail_namespace_user_disable_setgroups(struct minijail* j) {}
Dylan Reid837c74a2016-01-22 17:25:21 -0800521
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700522void minijail_namespace_vfs(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700523 ++libcontainer::g_mock_minijail_state->vfs_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800524}
525
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700526void minijail_namespace_ipc(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700527 ++libcontainer::g_mock_minijail_state->ipc_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800528}
529
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700530void minijail_namespace_net(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700531 ++libcontainer::g_mock_minijail_state->net_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800532}
533
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700534void minijail_namespace_pids(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700535 ++libcontainer::g_mock_minijail_state->pids_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800536}
537
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700538void minijail_namespace_user(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700539 ++libcontainer::g_mock_minijail_state->user_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800540}
541
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700542void minijail_namespace_cgroups(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700543 ++libcontainer::g_mock_minijail_state->cgroups_called_count;
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700544}
545
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700546int minijail_uidmap(struct minijail* j, const char* uidmap) {
547 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800548}
549
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700550int minijail_gidmap(struct minijail* j, const char* gidmap) {
551 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800552}
553
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700554int minijail_enter_pivot_root(struct minijail* j, const char* dir) {
555 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800556}
557
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700558void minijail_run_as_init(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700559 ++libcontainer::g_mock_minijail_state->run_as_init_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800560}
561
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700562int minijail_run_pid_pipes_no_preload(struct minijail* j,
563 const char* filename,
564 char* const argv[],
565 pid_t* pchild_pid,
566 int* pstdin_fd,
567 int* pstdout_fd,
568 int* pstderr_fd) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700569 libcontainer::g_mock_minijail_state->pid = fork();
570 if (libcontainer::g_mock_minijail_state->pid == -1)
571 return libcontainer::g_mock_minijail_state->pid;
572
573 if (libcontainer::g_mock_minijail_state->pid == 0) {
574 for (minijail_hook_event_t event : {MINIJAIL_HOOK_EVENT_PRE_CHROOT,
575 MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS,
576 MINIJAIL_HOOK_EVENT_PRE_EXECVE}) {
577 auto it = libcontainer::g_mock_minijail_state->hooks.find(event);
578 if (it == libcontainer::g_mock_minijail_state->hooks.end())
579 continue;
580 for (auto& hook : it->second) {
581 int rc = hook.Run();
582 if (rc)
583 _exit(rc);
584 }
585 }
586 _exit(0);
587 }
588
589 *pchild_pid = libcontainer::g_mock_minijail_state->pid;
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700590 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800591}
592
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700593int minijail_write_pid_file(struct minijail* j, const char* path) {
594 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800595}
596
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700597int minijail_wait(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700598 ++libcontainer::g_mock_minijail_state->wait_called_count;
599 int status;
600 if (HANDLE_EINTR(
601 waitpid(libcontainer::g_mock_minijail_state->pid, &status, 0)) < 0) {
Luis Hector Chavezdc61f8d2017-10-02 11:12:46 -0700602 PLOG(ERROR) << "Failed to wait for minijail";
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700603 return -errno;
604 }
605 if (!WIFEXITED(status)) {
606 LOG(ERROR) << "minijail terminated abnormally: " << std::hex << status;
607 return -ECANCELED;
608 }
609 // Exit status gets truncated to 8 bits. This should sign-extend it so that
610 // any negative values we passed are preserved.
611 return static_cast<int8_t>(WEXITSTATUS(status));
Dylan Reid837c74a2016-01-22 17:25:21 -0800612}
613
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700614int minijail_use_alt_syscall(struct minijail* j, const char* table) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700615 libcontainer::g_mock_minijail_state->alt_syscall_table = table;
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700616 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800617}
618
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700619int minijail_add_to_cgroup(struct minijail* j, const char* cg_path) {
620 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800621}
622
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700623void minijail_reset_signal_mask(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700624 ++libcontainer::g_mock_minijail_state->reset_signal_mask_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800625}
626
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700627void minijail_skip_remount_private(struct minijail* j) {}
Dylan Reid837c74a2016-01-22 17:25:21 -0800628
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700629int minijail_preserve_fd(struct minijail* j, int parent_fd, int child_fd) {
630 return 0;
631}
632
633int minijail_add_hook(struct minijail* j,
634 minijail_hook_t hook,
635 void* payload,
636 minijail_hook_event_t event) {
637 auto it = libcontainer::g_mock_minijail_state->hooks.insert(
638 std::make_pair(event, std::vector<libcontainer::MinijailHookCallback>()));
639 it.first->second.emplace_back(base::Bind(hook, base::Unretained(payload)));
640 return 0;
641}
642
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700643void minijail_close_open_fds(struct minijail* j) {}
644
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700645} // extern "C"