blob: 847b151c1e84bb6208bf47af7844c1bf99f0a9e5 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "patchpanel/minijailed_process_runner.h"
#include <linux/capability.h>
#include <sys/types.h>
#include <memory>
#include <brillo/minijail/mock_minijail.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "patchpanel/net_util.h"
#include "patchpanel/system.h"
using testing::_;
using testing::DoAll;
using testing::ElementsAre;
using testing::ElementsAreArray;
using testing::Eq;
using testing::Return;
using testing::SetArgPointee;
using testing::StrEq;
namespace patchpanel {
namespace {
class MockSystem : public System {
public:
MOCK_METHOD3(WaitPid, pid_t(pid_t pid, int* wstatus, int options));
};
TEST(MinijailProcessRunnerTest, modprobe_all) {
brillo::MockMinijail mj;
auto system = new MockSystem();
MinijailedProcessRunner runner(&mj, std::unique_ptr<System>(system));
uint64_t caps = CAP_TO_MASK(CAP_SYS_MODULE);
pid_t pid = 123;
EXPECT_CALL(mj, New());
EXPECT_CALL(mj, DropRoot(_, StrEq("nobody"), StrEq("nobody")))
.WillOnce(Return(true));
EXPECT_CALL(mj, UseCapabilities(_, Eq(caps)));
EXPECT_CALL(mj, RunPipesAndDestroy(
_,
ElementsAre(StrEq("/sbin/modprobe"), StrEq("-a"),
StrEq("module1"), StrEq("module2"), nullptr),
_, nullptr, nullptr, nullptr))
.WillOnce(DoAll(SetArgPointee<2>(pid), Return(true)));
EXPECT_CALL(*system, WaitPid(pid, _, _))
.WillOnce(DoAll(SetArgPointee<1>(1), Return(pid)));
EXPECT_TRUE(runner.modprobe_all({"module1", "module2"}));
}
TEST(MinijailProcessRunnerTest, ip) {
brillo::MockMinijail mj;
auto system = new MockSystem();
MinijailedProcessRunner runner(&mj, std::unique_ptr<System>(system));
uint64_t caps = CAP_TO_MASK(CAP_NET_ADMIN) | CAP_TO_MASK(CAP_NET_RAW);
pid_t pid = 123;
EXPECT_CALL(mj, New());
EXPECT_CALL(mj, DropRoot(_, StrEq("nobody"), StrEq("nobody")))
.WillOnce(Return(true));
EXPECT_CALL(mj, UseCapabilities(_, Eq(caps)));
EXPECT_CALL(mj, RunPipesAndDestroy(
_,
ElementsAre(StrEq("/bin/ip"), StrEq("obj"), StrEq("cmd"),
StrEq("arg1"), StrEq("arg2"), nullptr),
_, nullptr, nullptr, nullptr))
.WillOnce(DoAll(SetArgPointee<2>(pid), Return(true)));
EXPECT_CALL(*system, WaitPid(pid, _, _))
.WillOnce(DoAll(SetArgPointee<1>(1), Return(pid)));
EXPECT_TRUE(runner.ip("obj", "cmd", {"arg1", "arg2"}));
}
TEST(MinijailProcessRunnerTest, ip6) {
brillo::MockMinijail mj;
auto system = new MockSystem();
MinijailedProcessRunner runner(&mj, std::unique_ptr<System>(system));
uint64_t caps = CAP_TO_MASK(CAP_NET_ADMIN) | CAP_TO_MASK(CAP_NET_RAW);
pid_t pid = 123;
EXPECT_CALL(mj, New());
EXPECT_CALL(mj, DropRoot(_, StrEq("nobody"), StrEq("nobody")))
.WillOnce(Return(true));
EXPECT_CALL(mj, UseCapabilities(_, Eq(caps)));
EXPECT_CALL(
mj, RunPipesAndDestroy(
_,
ElementsAre(StrEq("/bin/ip"), StrEq("-6"), StrEq("obj"),
StrEq("cmd"), StrEq("arg1"), StrEq("arg2"), nullptr),
_, nullptr, nullptr, nullptr))
.WillOnce(DoAll(SetArgPointee<2>(pid), Return(true)));
EXPECT_CALL(*system, WaitPid(pid, _, _))
.WillOnce(DoAll(SetArgPointee<1>(1), Return(pid)));
EXPECT_TRUE(runner.ip6("obj", "cmd", {"arg1", "arg2"}));
}
TEST(MinijailProcessRunnerTest, iptables) {
brillo::MockMinijail mj;
auto system = new MockSystem();
MinijailedProcessRunner runner(&mj, std::unique_ptr<System>(system));
pid_t pid = 123;
EXPECT_CALL(mj, New());
EXPECT_CALL(mj, DropRoot(_, _, _)).Times(0);
EXPECT_CALL(mj, UseCapabilities(_, _)).Times(0);
EXPECT_CALL(
mj, RunPipesAndDestroy(
_,
ElementsAre(StrEq("/sbin/iptables"), StrEq("-t"), StrEq("table"),
StrEq("arg1"), StrEq("arg2"), nullptr),
_, nullptr, nullptr, nullptr))
.WillOnce(DoAll(SetArgPointee<2>(pid), Return(true)));
EXPECT_CALL(*system, WaitPid(pid, _, _))
.WillOnce(DoAll(SetArgPointee<1>(1), Return(pid)));
EXPECT_TRUE(runner.iptables("table", {"arg1", "arg2"}));
}
TEST(MinijailProcessRunnerTest, ip6tables) {
brillo::MockMinijail mj;
auto system = new MockSystem();
MinijailedProcessRunner runner(&mj, std::unique_ptr<System>(system));
pid_t pid = 123;
EXPECT_CALL(mj, New());
EXPECT_CALL(mj, DropRoot(_, _, _)).Times(0);
EXPECT_CALL(mj, UseCapabilities(_, _)).Times(0);
EXPECT_CALL(
mj, RunPipesAndDestroy(
_,
ElementsAre(StrEq("/sbin/ip6tables"), StrEq("-t"), StrEq("table"),
StrEq("arg1"), StrEq("arg2"), nullptr),
_, nullptr, nullptr, nullptr))
.WillOnce(DoAll(SetArgPointee<2>(pid), Return(true)));
EXPECT_CALL(*system, WaitPid(pid, _, _))
.WillOnce(DoAll(SetArgPointee<1>(1), Return(pid)));
EXPECT_TRUE(runner.ip6tables("table", {"arg1", "arg2"}));
}
} // namespace
} // namespace patchpanel