blob: 986c8e5ef1e2b24765c60dcd0db145ef2e3e43f2 [file] [log] [blame]
Greg Kerr888f1ce2019-01-31 10:49:11 -08001// Copyright 2019 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.
4
5#include "debugd/src/scheduler_configuration_tool.h"
6
7#include "debugd/src/error_utils.h"
Hardik Goyalb09d6b02019-08-13 16:15:50 -07008#include "debugd/src/helper_utils.h"
Greg Kerr888f1ce2019-01-31 10:49:11 -08009#include "debugd/src/process_with_output.h"
10#include "debugd/src/sandboxed_process.h"
11
12#include <string>
13
14#include <base/files/file_util.h>
15#include <base/logging.h>
16#include <base/strings/string_number_conversions.h>
17#include <base/strings/string_split.h>
18#include <base/strings/stringprintf.h>
19#include <brillo/errors/error_codes.h>
20#include <build/build_config.h>
21#include <build/buildflag.h>
22#include <chromeos/dbus/service_constants.h>
23
24namespace debugd {
25
26namespace {
27
28constexpr char kErrorPath[] =
29 "org.chromium.debugd.SchedulerConfigurationPolicyError";
30
Abhishek Bhardwaj08d907e2019-08-27 14:22:41 -070031const char kConservativePolicy[] = "conservative";
32
33const char kPerformancePolicy[] = "performance";
34
35bool IsValidSchedulerPolicy(const std::string& policy) {
36 return ((policy == kConservativePolicy) || (policy == kPerformancePolicy));
37}
38
Greg Kerr888f1ce2019-01-31 10:49:11 -080039constexpr bool IsX86_64() {
40#if defined(__x86_64__)
41 return true;
42#else
43 return false;
44#endif
45}
46
47// Executes a helper process with the expectation that any message printed to
48// stderr indicates a failure that should be passed back over D-Bus.
49// Returns false if any errors launching the process occur. Returns true
50// otherwise, and sets |exit_status| if it isn't null.
51bool RunHelper(const std::string& command,
52 const ProcessWithOutput::ArgList& arguments,
Yusuke Satob64c3562019-09-19 11:28:34 -070053 std::string* stdout,
Greg Kerr888f1ce2019-01-31 10:49:11 -080054 int* exit_status,
55 brillo::ErrorPtr* error) {
56 std::string helper_path;
Hardik Goyalb09d6b02019-08-13 16:15:50 -070057 if (!GetHelperPath(command, &helper_path)) {
Greg Kerr888f1ce2019-01-31 10:49:11 -080058 DEBUGD_ADD_ERROR(error, kErrorPath, "Path too long");
59 return false;
60 }
61
62 // Note: This runs the helper as root and without a sandbox only because the
63 // helper immediately drops privileges and enforces its own sandbox. debugd
64 // should not be used to launch unsandboxed executables.
65 std::string stderr;
66 int result = ProcessWithOutput::RunProcess(
67 helper_path, arguments, true /*requires_root*/,
Yusuke Satob64c3562019-09-19 11:28:34 -070068 true /* disable_sandbox */, nullptr, stdout, &stderr, error);
Greg Kerr888f1ce2019-01-31 10:49:11 -080069
70 if (!stderr.empty()) {
71 DEBUGD_ADD_ERROR(error, kErrorPath, stderr.c_str());
72 return false;
73 }
74
75 if (exit_status)
76 *exit_status = result;
77 return true;
78}
79
80} // namespace
81
82bool SchedulerConfigurationTool::SetPolicy(const std::string& policy,
Abhishek Bhardwaj08d907e2019-08-27 14:22:41 -070083 bool lock_policy,
Yusuke Satob64c3562019-09-19 11:28:34 -070084 brillo::ErrorPtr* error,
85 uint32_t* num_cores_disabled) {
86 *num_cores_disabled = 0;
87
Greg Kerr888f1ce2019-01-31 10:49:11 -080088 if (!IsX86_64()) {
89 DEBUGD_ADD_ERROR(error, kErrorPath, "Invalid architecture");
90 return false;
91 }
92
Abhishek Bhardwaj08d907e2019-08-27 14:22:41 -070093 if (!IsValidSchedulerPolicy(policy)) {
94 DEBUGD_ADD_ERROR(error, kErrorPath, "Invalid policy " + policy);
95 return false;
96 }
97 bool is_policy_conservative = (policy == kConservativePolicy);
98
99 if (policy_locked_conservative_) {
100 if (is_policy_conservative)
101 return true;
102
103 DEBUGD_ADD_ERROR(error, kErrorPath, "Policy locked to conservative");
104 return false;
105 }
106
107 if (lock_policy && !is_policy_conservative) {
108 DEBUGD_ADD_ERROR(error, kErrorPath, "Can't lock performance policy");
109 return false;
110 }
111
Greg Kerr888f1ce2019-01-31 10:49:11 -0800112 int exit_status;
Yusuke Satob64c3562019-09-19 11:28:34 -0700113 std::string stdout;
Greg Kerr888f1ce2019-01-31 10:49:11 -0800114 bool result = RunHelper("scheduler_configuration_helper",
115 ProcessWithOutput::ArgList{"--policy=" + policy},
Yusuke Satob64c3562019-09-19 11:28:34 -0700116 &stdout, &exit_status, error);
Greg Kerre0d17fd2019-02-19 14:51:30 -0800117
Yusuke Satob64c3562019-09-19 11:28:34 -0700118 bool status = base::StringToUint(
119 stdout, num_cores_disabled) && result && (exit_status == 0);
Greg Kerre0d17fd2019-02-19 14:51:30 -0800120 if (!status) {
121 DEBUGD_ADD_ERROR(error, kErrorPath,
Yusuke Satob64c3562019-09-19 11:28:34 -0700122 "scheduler_configuration_helper failed: stdout=" + stdout);
Abhishek Bhardwaj08d907e2019-08-27 14:22:41 -0700123 } else {
124 // The |policy_locked_conservative_| flag will only be set, if a
125 // "conservative" policy was successfully set when it was asked to be
126 // locked..
127 policy_locked_conservative_ = is_policy_conservative && lock_policy;
Greg Kerre0d17fd2019-02-19 14:51:30 -0800128 }
129
130 return status;
Greg Kerr888f1ce2019-01-31 10:49:11 -0800131}
132
133} // namespace debugd