| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 1 | /* | 
| Felipe Leme | 6f674ae | 2016-11-18 17:10:33 -0800 | [diff] [blame] | 2 | * Copyright (C) 2016 The Android Open Source Project | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
| Felipe Leme | 47e9be2 | 2016-12-21 15:37:07 -0800 | [diff] [blame] | 16 | #ifndef ANDROID_OS_DUMPSTATE_UTIL_H_ | 
|  | 17 | #define ANDROID_OS_DUMPSTATE_UTIL_H_ | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 18 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 19 | #include <cstdint> | 
|  | 20 | #include <string> | 
|  | 21 |  | 
| Vishnu Nair | 6921f80 | 2017-11-22 09:17:23 -0800 | [diff] [blame] | 22 | /* | 
|  | 23 | * Converts seconds to milliseconds. | 
|  | 24 | */ | 
|  | 25 | #define SEC_TO_MSEC(second) (second * 1000) | 
|  | 26 |  | 
|  | 27 | /* | 
|  | 28 | * Converts milliseconds to seconds. | 
|  | 29 | */ | 
|  | 30 | #define MSEC_TO_SEC(millisecond) (millisecond / 1000) | 
|  | 31 |  | 
| Felipe Leme | 47e9be2 | 2016-12-21 15:37:07 -0800 | [diff] [blame] | 32 | namespace android { | 
|  | 33 | namespace os { | 
|  | 34 | namespace dumpstate { | 
| Felipe Leme | 6f674ae | 2016-11-18 17:10:33 -0800 | [diff] [blame] | 35 |  | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 36 | /* | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 37 | * Defines the Linux account that should be executing a command. | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 38 | */ | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 39 | enum PrivilegeMode { | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 40 | /* Explicitly change the `uid` and `gid` to be `shell`.*/ | 
|  | 41 | DROP_ROOT, | 
|  | 42 | /* Don't change the `uid` and `gid`. */ | 
|  | 43 | DONT_DROP_ROOT, | 
|  | 44 | /* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */ | 
|  | 45 | SU_ROOT | 
|  | 46 | }; | 
|  | 47 |  | 
|  | 48 | /* | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 49 | * Defines what should happen with the main output stream (`stdout` or fd) of a command. | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 50 | */ | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 51 | enum OutputMode { | 
|  | 52 | /* Don't change main output. */ | 
|  | 53 | NORMAL_OUTPUT, | 
|  | 54 | /* Redirect main output to `stderr`. */ | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 55 | REDIRECT_TO_STDERR | 
|  | 56 | }; | 
|  | 57 |  | 
|  | 58 | /* | 
|  | 59 | * Value object used to set command options. | 
|  | 60 | * | 
|  | 61 | * Typically constructed using a builder with chained setters. Examples: | 
|  | 62 | * | 
|  | 63 | *  CommandOptions::WithTimeout(20).AsRoot().Build(); | 
|  | 64 | *  CommandOptions::WithTimeout(10).Always().RedirectStderr().Build(); | 
|  | 65 | * | 
|  | 66 | * Although the builder could be used to dynamically set values. Example: | 
|  | 67 | * | 
|  | 68 | *  CommandOptions::CommandOptionsBuilder options = | 
|  | 69 | *  CommandOptions::WithTimeout(10); | 
|  | 70 | *  if (!is_user_build()) { | 
|  | 71 | *    options.AsRoot(); | 
|  | 72 | *  } | 
|  | 73 | *  RunCommand("command", {"args"}, options.Build()); | 
|  | 74 | */ | 
|  | 75 | class CommandOptions { | 
|  | 76 | private: | 
|  | 77 | class CommandOptionsValues { | 
|  | 78 | private: | 
| Chih-Hung Hsieh | d0937e6 | 2018-12-20 15:43:57 -0800 | [diff] [blame] | 79 | explicit CommandOptionsValues(int64_t timeout_ms); | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 80 |  | 
| Vishnu Nair | 6921f80 | 2017-11-22 09:17:23 -0800 | [diff] [blame] | 81 | int64_t timeout_ms_; | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 82 | bool always_; | 
| Primiano Tucci | faaaafb | 2021-01-14 12:26:29 +0000 | [diff] [blame] | 83 | bool close_all_fds_on_exec_; | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 84 | PrivilegeMode account_mode_; | 
|  | 85 | OutputMode output_mode_; | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 86 | std::string logging_message_; | 
|  | 87 |  | 
|  | 88 | friend class CommandOptions; | 
|  | 89 | friend class CommandOptionsBuilder; | 
|  | 90 | }; | 
|  | 91 |  | 
| Chih-Hung Hsieh | d0937e6 | 2018-12-20 15:43:57 -0800 | [diff] [blame] | 92 | explicit CommandOptions(const CommandOptionsValues& values); | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 93 |  | 
|  | 94 | const CommandOptionsValues values; | 
|  | 95 |  | 
|  | 96 | public: | 
|  | 97 | class CommandOptionsBuilder { | 
|  | 98 | public: | 
|  | 99 | /* Sets the command to always run, even on `dry-run` mode. */ | 
|  | 100 | CommandOptionsBuilder& Always(); | 
| Nandana Dutt | 4b392be | 2018-11-02 16:17:05 +0000 | [diff] [blame] | 101 | /* | 
|  | 102 | * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property | 
|  | 103 | * 'dumpstate.unroot'. | 
|  | 104 | */ | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 105 | CommandOptionsBuilder& AsRoot(); | 
| Nandana Dutt | 4b392be | 2018-11-02 16:17:05 +0000 | [diff] [blame] | 106 | /* | 
|  | 107 | * Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is | 
|  | 108 | * not available. This is used for commands that return some useful information even | 
|  | 109 | * when run as shell. | 
|  | 110 | */ | 
| Yifan Hong | 48e83a1 | 2017-10-03 14:10:07 -0700 | [diff] [blame] | 111 | CommandOptionsBuilder& AsRootIfAvailable(); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 112 | /* Sets the command's PrivilegeMode as `DROP_ROOT` */ | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 113 | CommandOptionsBuilder& DropRoot(); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 114 | /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */ | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 115 | CommandOptionsBuilder& RedirectStderr(); | 
| Primiano Tucci | faaaafb | 2021-01-14 12:26:29 +0000 | [diff] [blame] | 116 | /* Closes all file descriptors before exec-ing the target process. This | 
|  | 117 | * includes also stdio pipes, which are dup-ed on /dev/null. It prevents | 
|  | 118 | * leaking opened FDs to the target process, which in turn can hit | 
|  | 119 | * selinux denials in presence of auto_trans rules. | 
|  | 120 | */ | 
|  | 121 | CommandOptionsBuilder& CloseAllFileDescriptorsOnExec(); | 
|  | 122 |  | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 123 | /* When not empty, logs a message before executing the command. | 
|  | 124 | * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ | 
|  | 125 | CommandOptionsBuilder& Log(const std::string& message); | 
|  | 126 | /* Builds the command options. */ | 
|  | 127 | CommandOptions Build(); | 
|  | 128 |  | 
|  | 129 | private: | 
| Chih-Hung Hsieh | d0937e6 | 2018-12-20 15:43:57 -0800 | [diff] [blame] | 130 | explicit CommandOptionsBuilder(int64_t timeout_ms); | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 131 | CommandOptionsValues values; | 
|  | 132 | friend class CommandOptions; | 
|  | 133 | }; | 
|  | 134 |  | 
| Vishnu Nair | 6921f80 | 2017-11-22 09:17:23 -0800 | [diff] [blame] | 135 | /** Gets the command timeout in seconds. */ | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 136 | int64_t Timeout() const; | 
| Vishnu Nair | 6921f80 | 2017-11-22 09:17:23 -0800 | [diff] [blame] | 137 | /** Gets the command timeout in milliseconds. */ | 
|  | 138 | int64_t TimeoutInMs() const; | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 139 | /* Checks whether the command should always be run, even on dry-run mode. */ | 
|  | 140 | bool Always() const; | 
| Primiano Tucci | faaaafb | 2021-01-14 12:26:29 +0000 | [diff] [blame] | 141 | /* Checks whether all FDs should be closed prior to the exec() calls. */ | 
|  | 142 | bool ShouldCloseAllFileDescriptorsOnExec() const; | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 143 | /** Gets the PrivilegeMode of the command. */ | 
|  | 144 | PrivilegeMode PrivilegeMode() const; | 
|  | 145 | /** Gets the OutputMode of the command. */ | 
|  | 146 | OutputMode OutputMode() const; | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 147 | /** Gets the logging message header, it any. */ | 
|  | 148 | std::string LoggingMessage() const; | 
|  | 149 |  | 
| Vishnu Nair | 6921f80 | 2017-11-22 09:17:23 -0800 | [diff] [blame] | 150 | /** Creates a builder with the requied timeout in seconds. */ | 
|  | 151 | static CommandOptionsBuilder WithTimeout(int64_t timeout_sec); | 
|  | 152 |  | 
|  | 153 | /** Creates a builder with the requied timeout in milliseconds. */ | 
|  | 154 | static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms); | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 155 |  | 
|  | 156 | // Common options. | 
|  | 157 | static CommandOptions DEFAULT; | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 158 | static CommandOptions AS_ROOT; | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 159 | }; | 
|  | 160 |  | 
|  | 161 | /* | 
|  | 162 | * System properties helper. | 
|  | 163 | */ | 
|  | 164 | class PropertiesHelper { | 
|  | 165 | friend class DumpstateBaseTest; | 
|  | 166 |  | 
|  | 167 | public: | 
|  | 168 | /* | 
|  | 169 | * Gets whether device is running a `user` build. | 
|  | 170 | */ | 
|  | 171 | static bool IsUserBuild(); | 
|  | 172 |  | 
|  | 173 | /* | 
|  | 174 | * When running in dry-run mode, skips the real dumps and just print the section headers. | 
|  | 175 | * | 
|  | 176 | * Useful when debugging dumpstate or other bugreport-related activities. | 
|  | 177 | * | 
|  | 178 | * Dry-run mode is enabled by setting the system property `dumpstate.dry_run` to true. | 
|  | 179 | */ | 
|  | 180 | static bool IsDryRun(); | 
|  | 181 |  | 
| Nandana Dutt | 4b392be | 2018-11-02 16:17:05 +0000 | [diff] [blame] | 182 | /** | 
|  | 183 | * Checks whether root availability should be overridden. | 
|  | 184 | * | 
|  | 185 | * Useful to verify how dumpstate would work in a device with an user build. | 
|  | 186 | */ | 
|  | 187 | static bool IsUnroot(); | 
|  | 188 |  | 
| Rhed Jao | 1c85512 | 2020-07-16 17:37:39 +0800 | [diff] [blame] | 189 | /* | 
|  | 190 | * Whether or not the parallel run is enabled. Setting the system property | 
|  | 191 | * 'dumpstate.parallel_run' to false to disable it, otherwise it returns | 
|  | 192 | * true by default. | 
|  | 193 | */ | 
|  | 194 | static bool IsParallelRun(); | 
|  | 195 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 196 | private: | 
|  | 197 | static std::string build_type_; | 
|  | 198 | static int dry_run_; | 
| Nandana Dutt | 4b392be | 2018-11-02 16:17:05 +0000 | [diff] [blame] | 199 | static int unroot_; | 
| Rhed Jao | 1c85512 | 2020-07-16 17:37:39 +0800 | [diff] [blame] | 200 | static int parallel_run_; | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 201 | }; | 
|  | 202 |  | 
|  | 203 | /* | 
|  | 204 | * Forks a command, waits for it to finish, and returns its status. | 
|  | 205 | * | 
|  | 206 | * |fd| file descriptor that receives the command's 'stdout'. | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 207 | * |title| description of the command printed on `stdout` (or empty to skip | 
|  | 208 | * description). | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 209 | * |full_command| array containing the command (first entry) and its arguments. | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 210 | *                Must contain at least one element. | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 211 | * |options| optional argument defining the command's behavior. | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 212 | */ | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 213 | int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command, | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 214 | const CommandOptions& options = CommandOptions::DEFAULT); | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 215 |  | 
|  | 216 | /* | 
|  | 217 | * Dumps the contents of a file into a file descriptor. | 
|  | 218 | * | 
|  | 219 | * |fd| file descriptor where the file is dumped into. | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 220 | * |title| description of the command printed on `stdout` (or empty to skip | 
|  | 221 | * description). | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 222 | * |path| location of the file to be dumped. | 
|  | 223 | */ | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 224 | int DumpFileToFd(int fd, const std::string& title, const std::string& path); | 
| Felipe Leme | bda15a0 | 2016-11-16 17:48:25 -0800 | [diff] [blame] | 225 |  | 
| Felipe Leme | 47e9be2 | 2016-12-21 15:37:07 -0800 | [diff] [blame] | 226 | }  // namespace dumpstate | 
|  | 227 | }  // namespace os | 
|  | 228 | }  // namespace android | 
|  | 229 |  | 
|  | 230 | #endif  // ANDROID_OS_DUMPSTATE_UTIL_H_ |