blob: 3791c6f2832cb02f54a298e4c74063c14e162f10 [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 -0700197TEST(LibcontainerTest, LogPreserve) {
Luis Hector Chavez835d39e2017-09-19 15:16:31 -0700198 errno = EPERM;
199 PLOG_PRESERVE(ERROR) << "This is an expected error log";
200 ASSERT_EQ(EPERM, errno);
201}
202
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700203class ContainerTest : public ::testing::Test {
204 public:
205 ContainerTest() = default;
206 ~ContainerTest() override = default;
Dylan Reid837c74a2016-01-22 17:25:21 -0800207
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700208 void SetUp() override {
209 g_mock_posix_state = new MockPosixState();
210 g_mock_cgroup_state = new MockCgroupState();
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700211 g_mock_minijail_state = new MockMinijailState();
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700212 libcontainer::Cgroup::SetCgroupFactoryForTesting(&MockCgroup::Create);
Dylan Reid837c74a2016-01-22 17:25:21 -0800213
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700214 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700215
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700216 ASSERT_TRUE(base::CreateTemporaryDirInDir(
217 temp_dir_.path(), FILE_PATH_LITERAL("container_test"), &rootfs_));
Dylan Reid837c74a2016-01-22 17:25:21 -0800218
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700219 mount_flags_ = MS_NOSUID | MS_NODEV | MS_NOEXEC;
Dylan Reid837c74a2016-01-22 17:25:21 -0800220
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700221 config_.reset(new Config());
222 container_config_uid_map(config_->get(), "0 0 4294967295");
223 container_config_gid_map(config_->get(), "0 0 4294967295");
224 container_config_rootfs(config_->get(), rootfs_.value().c_str());
Dylan Reid837c74a2016-01-22 17:25:21 -0800225
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700226 static const char* kArgv[] = {
227 "/sbin/init",
228 };
229 container_config_program_argv(config_->get(), kArgv, 1);
230 container_config_alt_syscall_table(config_->get(), "testsyscalltable");
231 container_config_add_mount(config_->get(),
232 "testtmpfs",
233 "tmpfs",
234 "/tmp",
235 "tmpfs",
236 nullptr,
237 nullptr,
238 mount_flags_,
239 0,
240 1000,
241 1000,
242 0x666,
243 0,
244 0);
245 container_config_add_device(config_->get(),
246 'c',
247 "/dev/foo",
248 S_IRWXU | S_IRWXG,
249 245,
250 2,
251 0,
252 1000,
253 1001,
254 1,
255 1,
256 0);
257 // test dynamic minor on /dev/null
258 container_config_add_device(config_->get(),
259 'c',
260 "/dev/null",
261 S_IRWXU | S_IRWXG,
262 1,
263 -1,
264 1,
265 1000,
266 1001,
267 1,
268 1,
269 0);
Dylan Reid837c74a2016-01-22 17:25:21 -0800270
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700271 container_config_set_cpu_shares(config_->get(), kTestCpuShares);
272 container_config_set_cpu_cfs_params(
273 config_->get(), kTestCpuQuota, kTestCpuPeriod);
274 /* Invalid params, so this won't be applied. */
275 container_config_set_cpu_rt_params(config_->get(), 20000, 20000);
Dylan Reid837c74a2016-01-22 17:25:21 -0800276
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700277 base::FilePath rundir;
278 ASSERT_TRUE(base::CreateTemporaryDirInDir(
279 temp_dir_.path(), FILE_PATH_LITERAL("container_test_run"), &rundir));
280 container_.reset(new Container("containerUT", rundir));
281 ASSERT_NE(nullptr, container_.get());
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700282 }
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700283
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700284 void TearDown() override {
285 container_.reset();
286 config_.reset();
Dylan Reid837c74a2016-01-22 17:25:21 -0800287
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700288 ASSERT_TRUE(temp_dir_.Delete());
289 delete g_mock_posix_state;
290 g_mock_posix_state = nullptr;
291 libcontainer::Cgroup::SetCgroupFactoryForTesting(nullptr);
292 delete g_mock_cgroup_state;
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700293 delete g_mock_minijail_state;
294 g_mock_minijail_state = nullptr;
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700295 }
296
297 protected:
298 std::unique_ptr<Config> config_;
299 std::unique_ptr<Container> container_;
300 int mount_flags_;
301 base::FilePath rootfs_;
302
303 private:
304 base::ScopedTempDir temp_dir_;
305
306 DISALLOW_COPY_AND_ASSIGN(ContainerTest);
307};
308
309TEST_F(ContainerTest, TestMountTmpStart) {
310 ASSERT_EQ(0, container_start(container_->get(), config_->get()));
311 ASSERT_EQ(2, g_mock_posix_state->mount_args.size());
312 EXPECT_EQ(false, g_mock_posix_state->mount_args[1].outside_mount);
313 EXPECT_STREQ("tmpfs", g_mock_posix_state->mount_args[1].source.c_str());
314 EXPECT_STREQ("/tmp",
315 g_mock_posix_state->mount_args[1].target.value().c_str());
316 EXPECT_STREQ("tmpfs",
317 g_mock_posix_state->mount_args[1].filesystemtype.c_str());
318 EXPECT_EQ(g_mock_posix_state->mount_args[1].mountflags,
319 static_cast<unsigned long>(mount_flags_));
320 EXPECT_EQ(nullptr, g_mock_posix_state->mount_args[1].data);
Dylan Reid837c74a2016-01-22 17:25:21 -0800321
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700322 EXPECT_EQ(1, g_mock_minijail_state->ipc_called_count);
323 EXPECT_EQ(1, g_mock_minijail_state->vfs_called_count);
324 EXPECT_EQ(1, g_mock_minijail_state->net_called_count);
325 EXPECT_EQ(1, g_mock_minijail_state->pids_called_count);
326 EXPECT_EQ(1, g_mock_minijail_state->user_called_count);
327 EXPECT_EQ(1, g_mock_minijail_state->cgroups_called_count);
328 EXPECT_EQ(1, g_mock_minijail_state->run_as_init_called_count);
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700329 EXPECT_EQ(1, g_mock_cgroup_state->deny_all_devs_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800330
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700331 ASSERT_EQ(2, g_mock_cgroup_state->added_devices.size());
332 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].allow);
333 EXPECT_EQ(245, g_mock_cgroup_state->added_devices[0].major);
334 EXPECT_EQ(2, g_mock_cgroup_state->added_devices[0].minor);
335 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].read);
336 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[0].write);
337 EXPECT_EQ(0, g_mock_cgroup_state->added_devices[0].modify);
338 EXPECT_EQ('c', g_mock_cgroup_state->added_devices[0].type);
Dylan Reid355d5e42016-04-29 16:53:31 -0700339
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700340 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].allow);
341 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].major);
342 EXPECT_EQ(-1, g_mock_cgroup_state->added_devices[1].minor);
343 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].read);
344 EXPECT_EQ(1, g_mock_cgroup_state->added_devices[1].write);
345 EXPECT_EQ(0, g_mock_cgroup_state->added_devices[1].modify);
346 EXPECT_EQ('c', g_mock_cgroup_state->added_devices[1].type);
Dylan Reid837c74a2016-01-22 17:25:21 -0800347
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700348 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_shares_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700349 EXPECT_EQ(kTestCpuShares, container_config_get_cpu_shares(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700350 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_quota_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700351 EXPECT_EQ(kTestCpuQuota, container_config_get_cpu_quota(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700352 EXPECT_EQ(1, g_mock_cgroup_state->set_cpu_period_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700353 EXPECT_EQ(kTestCpuPeriod, container_config_get_cpu_period(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700354 EXPECT_EQ(0, g_mock_cgroup_state->set_cpu_rt_runtime_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700355 EXPECT_EQ(0, container_config_get_cpu_rt_runtime(config_->get()));
Luis Hector Chavez76ae9ac2017-09-20 21:13:08 -0700356 EXPECT_EQ(0, g_mock_cgroup_state->set_cpu_rt_period_count);
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700357 EXPECT_EQ(0, container_config_get_cpu_rt_period(config_->get()));
Chinyue Chenfac909e2016-06-24 14:17:42 +0800358
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700359 ASSERT_NE(std::string(), g_mock_minijail_state->alt_syscall_table);
360 EXPECT_EQ("testsyscalltable", g_mock_minijail_state->alt_syscall_table);
Dylan Reid837c74a2016-01-22 17:25:21 -0800361
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700362 EXPECT_EQ(0, container_wait(container_->get()));
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700363 EXPECT_EQ(1, g_mock_minijail_state->wait_called_count);
364 EXPECT_EQ(1, g_mock_minijail_state->reset_signal_mask_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800365}
366
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700367TEST_F(ContainerTest, TestKillContainer) {
368 ASSERT_EQ(0, container_start(container_->get(), config_->get()));
369 EXPECT_EQ(0, container_kill(container_->get()));
370 EXPECT_EQ(std::vector<int>{SIGKILL}, g_mock_posix_state->kill_sigs);
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700371 EXPECT_EQ(1, g_mock_minijail_state->wait_called_count);
Dylan Reid837c74a2016-01-22 17:25:21 -0800372}
373
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700374} // namespace libcontainer
375
376// libc stubs so the UT doesn't need root to call mount, etc.
Luis Hector Chavezf9b16872017-09-14 14:22:15 -0700377extern "C" {
378
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700379extern decltype(chmod) __real_chmod;
380int __wrap_chmod(const char* path, mode_t mode) {
381 if (!libcontainer::g_mock_posix_state)
382 return __real_chmod(path, mode);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700383 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800384}
385
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700386extern decltype(chown) __real_chown;
387int __wrap_chown(const char* path, uid_t owner, gid_t group) {
388 if (!libcontainer::g_mock_posix_state)
389 return __real_chown(path, owner, group);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700390 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800391}
392
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700393extern decltype(getuid) __real_getuid;
394uid_t __wrap_getuid(void) {
395 if (!libcontainer::g_mock_posix_state)
396 return __real_getuid();
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700397 return 0;
398}
399
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700400extern decltype(kill) __real_kill;
401int __wrap_kill(pid_t pid, int sig) {
402 if (!libcontainer::g_mock_posix_state)
403 return __real_kill(pid, sig);
404 libcontainer::g_mock_posix_state->kill_sigs.push_back(sig);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700405 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800406}
407
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700408extern decltype(mkdir) __real_mkdir;
409int __wrap_mkdir(const char* pathname, mode_t mode) {
410 if (!libcontainer::g_mock_posix_state)
411 return __real_mkdir(pathname, mode);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700412 return 0;
Luis Hector Chavez836d7b22017-09-14 15:11:15 -0700413}
Dylan Reid837c74a2016-01-22 17:25:21 -0800414
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700415extern decltype(mkdtemp) __real_mkdtemp;
416char* __wrap_mkdtemp(char* template_string) {
417 if (!libcontainer::g_mock_posix_state)
418 return __real_mkdtemp(template_string);
419 libcontainer::g_mock_posix_state->mkdtemp_root =
420 base::FilePath(template_string);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700421 return template_string;
Dylan Reid837c74a2016-01-22 17:25:21 -0800422}
423
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700424extern decltype(mount) __real_mount;
425int __wrap_mount(const char* source,
426 const char* target,
427 const char* filesystemtype,
428 unsigned long mountflags,
429 const void* data) {
430 if (!libcontainer::g_mock_posix_state)
431 return __real_mount(source, target, filesystemtype, mountflags, data);
432
433 libcontainer::g_mock_posix_state->mount_args.emplace_back(
434 libcontainer::MockPosixState::MountArgs{source,
435 base::FilePath(target),
436 filesystemtype,
437 mountflags,
438 data,
439 true});
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700440 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800441}
442
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700443extern decltype(rmdir) __real_rmdir;
444int __wrap_rmdir(const char* pathname) {
445 if (!libcontainer::g_mock_posix_state)
446 return __real_rmdir(pathname);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700447 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800448}
449
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700450extern decltype(umount) __real_umount;
451int __wrap_umount(const char* target) {
452 if (!libcontainer::g_mock_posix_state)
453 return __real_umount(target);
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700454 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800455}
456
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700457extern decltype(umount2) __real_umount2;
458int __wrap_umount2(const char* target, int flags) {
459 if (!libcontainer::g_mock_posix_state)
460 return __real_umount2(target, flags);
461 return 0;
462}
463
464extern decltype(unlink) __real_unlink;
465int __wrap_unlink(const char* pathname) {
466 if (!libcontainer::g_mock_posix_state)
467 return __real_unlink(pathname);
468 return 0;
469}
470
471extern decltype(__xmknod) __real___xmknod;
472int __wrap___xmknod(int ver, const char* pathname, mode_t mode, dev_t* dev) {
473 if (!libcontainer::g_mock_posix_state)
474 return __real___xmknod(ver, pathname, mode, dev);
475 return 0;
476}
477
478extern decltype(__xstat) __real___xstat;
479int __wrap___xstat(int ver, const char* path, struct stat* buf) {
480 if (!libcontainer::g_mock_posix_state)
481 return __real___xstat(ver, path, buf);
482 buf->st_rdev = libcontainer::g_mock_posix_state->stat_rdev_ret;
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700483 return 0;
484}
485
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700486extern decltype(setns) __real_setns;
487int __wrap_setns(int fd, int nstype) {
488 if (!libcontainer::g_mock_posix_state)
489 return __real_setns(fd, nstype);
490 return 0;
491}
492
Dylan Reid837c74a2016-01-22 17:25:21 -0800493/* Minijail stubs */
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700494struct minijail* minijail_new(void) {
495 return (struct minijail*)0x55;
Chinyue Chen03c54ae2016-06-29 12:29:10 +0800496}
497
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700498void minijail_destroy(struct minijail* j) {}
499
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700500int minijail_mount_with_data(struct minijail* j,
501 const char* source,
502 const char* target,
503 const char* filesystemtype,
504 unsigned long mountflags,
505 const char* data) {
Luis Hector Chavez58725a82017-09-19 21:14:17 -0700506 libcontainer::g_mock_posix_state->mount_args.emplace_back(
507 libcontainer::MockPosixState::MountArgs{source,
508 base::FilePath(target),
509 filesystemtype,
510 mountflags,
511 data,
512 false});
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700513 return 0;
514}
515
Luis Hector Chavezedec56e2017-09-19 15:43:53 -0700516void minijail_namespace_user_disable_setgroups(struct minijail* j) {}
Dylan Reid837c74a2016-01-22 17:25:21 -0800517
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700518void minijail_namespace_vfs(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700519 ++libcontainer::g_mock_minijail_state->vfs_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800520}
521
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700522void minijail_namespace_ipc(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700523 ++libcontainer::g_mock_minijail_state->ipc_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800524}
525
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700526void minijail_namespace_net(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700527 ++libcontainer::g_mock_minijail_state->net_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800528}
529
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700530void minijail_namespace_pids(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700531 ++libcontainer::g_mock_minijail_state->pids_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800532}
533
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700534void minijail_namespace_user(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700535 ++libcontainer::g_mock_minijail_state->user_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800536}
537
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700538void minijail_namespace_cgroups(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700539 ++libcontainer::g_mock_minijail_state->cgroups_called_count;
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700540}
541
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700542int minijail_uidmap(struct minijail* j, const char* uidmap) {
543 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800544}
545
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700546int minijail_gidmap(struct minijail* j, const char* gidmap) {
547 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800548}
549
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700550int minijail_enter_pivot_root(struct minijail* j, const char* dir) {
551 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800552}
553
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700554void minijail_run_as_init(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700555 ++libcontainer::g_mock_minijail_state->run_as_init_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800556}
557
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700558int minijail_run_pid_pipes_no_preload(struct minijail* j,
559 const char* filename,
560 char* const argv[],
561 pid_t* pchild_pid,
562 int* pstdin_fd,
563 int* pstdout_fd,
564 int* pstderr_fd) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700565 libcontainer::g_mock_minijail_state->pid = fork();
566 if (libcontainer::g_mock_minijail_state->pid == -1)
567 return libcontainer::g_mock_minijail_state->pid;
568
569 if (libcontainer::g_mock_minijail_state->pid == 0) {
570 for (minijail_hook_event_t event : {MINIJAIL_HOOK_EVENT_PRE_CHROOT,
571 MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS,
572 MINIJAIL_HOOK_EVENT_PRE_EXECVE}) {
573 auto it = libcontainer::g_mock_minijail_state->hooks.find(event);
574 if (it == libcontainer::g_mock_minijail_state->hooks.end())
575 continue;
576 for (auto& hook : it->second) {
577 int rc = hook.Run();
578 if (rc)
579 _exit(rc);
580 }
581 }
582 _exit(0);
583 }
584
585 *pchild_pid = libcontainer::g_mock_minijail_state->pid;
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700586 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800587}
588
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700589int minijail_write_pid_file(struct minijail* j, const char* path) {
590 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800591}
592
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700593int minijail_wait(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700594 ++libcontainer::g_mock_minijail_state->wait_called_count;
595 int status;
596 if (HANDLE_EINTR(
597 waitpid(libcontainer::g_mock_minijail_state->pid, &status, 0)) < 0) {
598 PLOG_PRESERVE(ERROR) << "Failed to wait for minijail";
599 return -errno;
600 }
601 if (!WIFEXITED(status)) {
602 LOG(ERROR) << "minijail terminated abnormally: " << std::hex << status;
603 return -ECANCELED;
604 }
605 // Exit status gets truncated to 8 bits. This should sign-extend it so that
606 // any negative values we passed are preserved.
607 return static_cast<int8_t>(WEXITSTATUS(status));
Dylan Reid837c74a2016-01-22 17:25:21 -0800608}
609
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700610int minijail_use_alt_syscall(struct minijail* j, const char* table) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700611 libcontainer::g_mock_minijail_state->alt_syscall_table = table;
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700612 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800613}
614
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700615int minijail_add_to_cgroup(struct minijail* j, const char* cg_path) {
616 return 0;
Dylan Reid837c74a2016-01-22 17:25:21 -0800617}
618
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700619void minijail_reset_signal_mask(struct minijail* j) {
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700620 ++libcontainer::g_mock_minijail_state->reset_signal_mask_called_count;
Dylan Reid837c74a2016-01-22 17:25:21 -0800621}
622
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700623void minijail_skip_remount_private(struct minijail* j) {}
Dylan Reid837c74a2016-01-22 17:25:21 -0800624
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700625int minijail_preserve_fd(struct minijail* j, int parent_fd, int child_fd) {
626 return 0;
627}
628
629int minijail_add_hook(struct minijail* j,
630 minijail_hook_t hook,
631 void* payload,
632 minijail_hook_event_t event) {
633 auto it = libcontainer::g_mock_minijail_state->hooks.insert(
634 std::make_pair(event, std::vector<libcontainer::MinijailHookCallback>()));
635 it.first->second.emplace_back(base::Bind(hook, base::Unretained(payload)));
636 return 0;
637}
638
Luis Hector Chavez9e03e172017-09-15 11:29:54 -0700639void minijail_close_open_fds(struct minijail* j) {}
640
Luis Hector Chavez31735bc2017-09-15 08:17:10 -0700641} // extern "C"