blob: a34fd72743e7b8fd7e7f228a01f716fff4947ebc [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 "debugd/src/helpers/scheduler_configuration_utils.h"
#include <libminijail.h>
#include <scoped_minijail.h>
#include <sys/prctl.h>
#include <string>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <brillo/flag_helper.h>
#include <brillo/syslog_logging.h>
#include <build/build_config.h>
#include <build/buildflag.h>
#include <chromeos/dbus/service_constants.h>
// Not all Linux kernels have this defined.
#ifndef PR_SET_CORE_SCHED
// TODO(b/152605392): Replace this with the final upstream interface.
#define PR_SET_CORE_SCHED 0x200
#endif
using debugd::scheduler_configuration::kConservativeScheduler;
using debugd::scheduler_configuration::kCoreIsolationScheduler;
using debugd::scheduler_configuration::kPerformanceScheduler;
namespace {
constexpr char kCPUPathPrefix[] = "/sys";
constexpr char kSeccompFilterPath[] =
"/usr/share/policy/scheduler-configuration-helper.policy";
constexpr char kDebugdUser[] = "debugd";
constexpr char kDebugdGroup[] = "debugd";
// Enters a minijail sandbox.
void EnterSandbox() {
ScopedMinijail jail(minijail_new());
minijail_no_new_privs(jail.get());
minijail_use_seccomp_filter(jail.get());
minijail_parse_seccomp_filters(jail.get(), kSeccompFilterPath);
minijail_reset_signal_mask(jail.get());
minijail_namespace_ipc(jail.get());
minijail_namespace_net(jail.get());
minijail_remount_proc_readonly(jail.get());
minijail_change_user(jail.get(), kDebugdUser);
minijail_change_group(jail.get(), kDebugdGroup);
minijail_namespace_vfs(jail.get());
minijail_bind(jail.get(), "/", "/", 0);
minijail_bind(jail.get(), "/proc", "/proc", 0);
minijail_bind(jail.get(), "/dev/log", "/dev/log", 0);
minijail_mount_dev(jail.get());
minijail_remount_proc_readonly(jail.get());
minijail_enter_pivot_root(jail.get(), "/mnt/empty");
minijail_bind(jail.get(), "/sys", "/sys", 1);
minijail_enter(jail.get());
}
} // namespace
int main(int argc, char* argv[]) {
brillo::InitLog(brillo::kLogToStderr);
std::string policy_flag =
std::string("Set to either ") + kConservativeScheduler + " or " +
kCoreIsolationScheduler + " or " + kPerformanceScheduler + ".";
DEFINE_string(policy, "", policy_flag.c_str());
brillo::FlagHelper::Init(argc, argv, "scheduler_configuration_helper");
if (FLAGS_policy != kConservativeScheduler &&
FLAGS_policy != kCoreIsolationScheduler &&
FLAGS_policy != kPerformanceScheduler) {
LOG(INFO) << "Unknown policy \"" << FLAGS_policy << "\", defaulting to "
<< kConservativeScheduler;
FLAGS_policy = kConservativeScheduler;
}
// The CPU control files must be opened as root.
base::FilePath base_path(kCPUPathPrefix);
debugd::SchedulerConfigurationUtils utils(base_path);
if (!utils.GetControlFDs()) {
LOG(ERROR) << "Failed to open CPU control files.";
return 1;
}
if (!utils.GetCPUSetFDs()) {
LOG(ERROR) << "Failed to open cpuset files.";
return 1;
}
EnterSandbox();
// By default, Chrome prefers to use core isolation scheduling, which keeps
// hyper-threading enabled globally, but puts renderer processes into
// untrusted execution groups. Chrome does not know which kernels support core
// scheduling, so debugd makes that decision, and defaults to conservative if
// core scheduling is not supported.
if (FLAGS_policy == kCoreIsolationScheduler) {
int ret = prctl(PR_SET_CORE_SCHED, 2);
DCHECK_LT(ret, 0); // This should never succeed.
if (errno == ERANGE) {
// The kernel supports the call but we gave it a bogus argument.
FLAGS_policy = kPerformanceScheduler;
} else {
FLAGS_policy = kConservativeScheduler;
}
}
int status = 1;
size_t num_cores_disabled = 0;
if (FLAGS_policy == kPerformanceScheduler) {
status = utils.EnablePerformanceConfiguration(&num_cores_disabled) ? 0 : 1;
} else if (FLAGS_policy == kConservativeScheduler) {
status = utils.EnableConservativeConfiguration(&num_cores_disabled) ? 0 : 1;
}
fprintf(stdout, "%zu", num_cores_disabled);
fflush(stdout);
return status;
}