• 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 
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 
32 namespace android {
33 namespace os {
34 namespace dumpstate {
35 
36 /*
37  * Defines the Linux account that should be executing a command.
38  */
39 enum PrivilegeMode {
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 /*
49  * Defines what should happen with the main output stream (`stdout` or fd) of a command.
50  */
51 enum OutputMode {
52     /* Don't change main output. */
53     NORMAL_OUTPUT,
54     /* Redirect main output to `stderr`. */
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:
79         explicit CommandOptionsValues(int64_t timeout_ms);
80 
81         int64_t timeout_ms_;
82         bool always_;
83         bool close_all_fds_on_exec_;
84         PrivilegeMode account_mode_;
85         OutputMode output_mode_;
86         std::string logging_message_;
87 
88         friend class CommandOptions;
89         friend class CommandOptionsBuilder;
90     };
91 
92     explicit CommandOptions(const CommandOptionsValues& values);
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();
101         /*
102          * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property
103          * 'dumpstate.unroot'.
104          */
105         CommandOptionsBuilder& AsRoot();
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          */
111         CommandOptionsBuilder& AsRootIfAvailable();
112         /* Sets the command's PrivilegeMode as `DROP_ROOT` */
113         CommandOptionsBuilder& DropRoot();
114         /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */
115         CommandOptionsBuilder& RedirectStderr();
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 
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:
130         explicit CommandOptionsBuilder(int64_t timeout_ms);
131         CommandOptionsValues values;
132         friend class CommandOptions;
133     };
134 
135     /** Gets the command timeout in seconds. */
136     int64_t Timeout() const;
137     /** Gets the command timeout in milliseconds. */
138     int64_t TimeoutInMs() const;
139     /* Checks whether the command should always be run, even on dry-run mode. */
140     bool Always() const;
141     /* Checks whether all FDs should be closed prior to the exec() calls. */
142     bool ShouldCloseAllFileDescriptorsOnExec() const;
143     /** Gets the PrivilegeMode of the command. */
144     PrivilegeMode PrivilegeMode() const;
145     /** Gets the OutputMode of the command. */
146     OutputMode OutputMode() const;
147     /** Gets the logging message header, it any. */
148     std::string LoggingMessage() const;
149 
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);
155 
156     // Common options.
157     static CommandOptions DEFAULT;
158     static CommandOptions AS_ROOT;
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 
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 
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 
196   private:
197     static std::string build_type_;
198     static int dry_run_;
199     static int unroot_;
200     static int parallel_run_;
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'.
207  * |title| description of the command printed on `stdout` (or empty to skip
208  * description).
209  * |full_command| array containing the command (first entry) and its arguments.
210  *                Must contain at least one element.
211  * |options| optional argument defining the command's behavior.
212  */
213 int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command,
214                    const CommandOptions& options = CommandOptions::DEFAULT);
215 
216 /*
217  * Dumps the contents of a file into a file descriptor.
218  *
219  * |fd| file descriptor where the file is dumped into.
220  * |title| description of the command printed on `stdout` (or empty to skip
221  * description).
222  * |path| location of the file to be dumped.
223  */
224 int DumpFileToFd(int fd, const std::string& title, const std::string& path);
225 
226 }  // namespace dumpstate
227 }  // namespace os
228 }  // namespace android
229 
230 #endif  // ANDROID_OS_DUMPSTATE_UTIL_H_
231