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