blob: 1daf232fdb69617f7337e460c31799131e1c846e [file] [log] [blame]
// Copyright 2022 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 "init/process_killer/process_manager.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_number_conversions.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <re2/re2.h>
#include <init/process_killer/process.h>
namespace init {
class ProcessManagerTest : public ::testing::Test {
public:
void SetUpProcess(pid_t pid,
const std::string& comm,
const std::string& mountinfo_contents,
const std::vector<OpenFileDescriptor>& fds) {
base::FilePath pid_dir =
tmp_dir_.GetPath().AppendASCII(base::NumberToString(pid));
ASSERT_TRUE(base::CreateDirectory(pid_dir));
// Set up mountinfo.
base::FilePath mountinfo = pid_dir.AppendASCII("mountinfo");
ASSERT_TRUE(base::WriteFile(mountinfo, mountinfo_contents));
// Set up comm for the process.
base::FilePath comm_path = pid_dir.AppendASCII("comm");
ASSERT_TRUE(base::WriteFile(comm_path, comm));
// Set up file descriptors.
base::FilePath fd_dir = pid_dir.AppendASCII("fd");
ASSERT_TRUE(base::CreateDirectory(fd_dir));
// Set up file descriptors. Add a few fake descriptors at the beginning to
// test handling of stdin/stdout/pipes.
ASSERT_TRUE(base::WriteFile(fd_dir.AppendASCII("0"), "foo"));
ASSERT_TRUE(base::WriteFile(fd_dir.AppendASCII("1"), "bar"));
ASSERT_TRUE(base::WriteFile(fd_dir.AppendASCII("2"), "baz"));
int current_fd = 3;
// Target dir contains the targets for the symbolic links.
base::FilePath target_dir = tmp_dir_.GetPath().AppendASCII("targets");
ASSERT_TRUE(base::CreateDirectory(target_dir));
for (auto& fd : fds) {
base::FilePath symlink =
fd_dir.AppendASCII(base::NumberToString(current_fd++));
base::FilePath target = target_dir.AppendASCII(fd.path.value());
ASSERT_TRUE(base::WriteFile(target, "foo"));
ASSERT_TRUE(base::CreateSymbolicLink(target, symlink));
}
}
void SetUp() override {
ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
pm_ = std::make_unique<ProcessManager>(tmp_dir_.GetPath());
}
protected:
base::ScopedTempDir tmp_dir_;
std::unique_ptr<ProcessManager> pm_;
};
TEST_F(ProcessManagerTest, InvalidProcessTest) {
ASSERT_TRUE(base::WriteFile(
tmp_dir_.GetPath().AppendASCII("proc").AppendASCII("123"), "foo", 3));
EXPECT_TRUE(pm_->GetProcessList().empty());
}
TEST_F(ProcessManagerTest, ValidProcessTest) {
std::string mountinfo = "21 12 8:1 /var /var rw,noexec - ext3 /dev/sda1 rw\n";
OpenFileDescriptor fd = {base::FilePath("foo")};
SetUpProcess(2, "foo", mountinfo, {fd});
std::vector<ActiveProcess> list = pm_->GetProcessList();
EXPECT_EQ(list.size(), 1);
ActiveProcess p = list[0];
EXPECT_TRUE(p.HasFileOpenOnMount(re2::RE2("foo")));
EXPECT_TRUE(p.HasMountOpenFromDevice(re2::RE2("/dev/sda1")));
}
} // namespace init